'tr' のように、2 つの文字列を受け取り、その間の文字列を抽出する単一コマンド (式なし)

'tr' のように、2 つの文字列を受け取り、その間の文字列を抽出する単一コマンド (式なし)

見たここ次のように、sed を使用して行内の他の 2 つの文字列の間にあるテキストを取得する方法:

sed 's/.*starting_text\(.*\)ending_text.*/\1/'

しかし、私は2つの文字列を受け取り、最初の文字列の前または2番目の文字列の後のすべてをトリミングする単純なコマンド( のようなものですが、文字列抽出用)が欲しいですtr。例:

grep something some_file | between message\"\:\" " with"

エスケープ文字も処理します。

答え1

区切り文字が 1 行に複数回出現する可能性がある場合は、代わりに次のように perl を使用できます。

between() {
  perl -Tlne 'BEGIN{$b=shift;$e=shift}
             print for /\Q$b\E(.*?)\Q$e\E/g' "$@"
}

そして例えば:

$ echo "[b]test[e] foo [b]bar[e]" | between '[b]' '[e]'
test
bar

次のように使用することもできます:

between BEG END file1 file2...

答え2

これをsedで一般的に行うには、部分文字列を見つけるために使用する正規表現の文字をエスケープする必要があります。ここ(注:詳細情報ここ問題が発生した場合にはご連絡ください。

そして、関数にパイプする方法を見つけましたここ

これらすべてを で使用できる関数にまとめると.bashrc、次のようになります (ただし、a 変数と b 変数を設定する必要はありませんが、読みやすくなります)。

between(){
  a=$(printf '%s\n' "$1"|sed 's![\*.^$/[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![\*.^$/[]!\\&!g')
  sed "s/.*$a\(.*\)$b.*/\1/"
}

ジョセフ・Rが述べたように、この答えgrep -oPを使用して同様のことを行う方法を示しています。Perl互換の正規表現をエスケープするには、これなので、おそらく次の方法も有効でしょう:

between(){
  a=$(printf '%s\n' "$1"|sed 's![]\*.^+?(){|$[]!\\&!g')
  b=$(printf '%s\n' "$2"|sed 's![]\*.^+?(){|$[]!\\&!g')
  grep -oP "(?=$a).*?(?=$b)"
}

関連情報