sed は行の先頭または文字と一致します。

sed は行の先頭または文字と一致します。

コロンで区切られた作業文字列があり、各形式はa=bfooを抽出するために解析する必要があります。ここでfooはです...:di=foo:...。割り当てはdi=foo、文字列の先頭、中間、または末尾で行うことができます。

私の考えは、行の先頭またはコロン、文字列、di=コロンを除くすべての文字、コロン、または行の終わりを一致させることです。

私は「コロンを除くすべての文字」部分だけを機能させました。

いくつかのテスト:

echo "di=a;b:*.di=c;d:ddi=e;f" | sed "s/.*di=\([^:]*\):.*/\1/"
echo "ddi=a;b:di=c;d:*.di=e;f" | sed "s/.*di=\([^:]*\):.*/\1/"
echo "*.di=a;b:ddi=c;d:di=e;f" | sed "s/.*di=\([^:]*\):.*/\1/"

最初の項目も返す必要がありa;b、2番目c;dと3番目の項目も返す必要がありますe;fが、両方とも返されますc;d

答え1

私の考えは、行の先頭またはコロンを一致させ、次に文字列di =を一致させ、コロンを除くすべての文字を一致させ、次にコロンまたは行の終わりを一致させることです。

例のように、「次のコロンまたは行末」を一致させる必要はありません。

{
echo "di=a;b:*.di=c;d:ddi=e;f"
echo "ddi=a;b:di=c;d:*.di=e;f"
echo "*.di=a;b:ddi=c;d:di=e;f"
} | sed 's/\(^\|.*:\)di=\([^:]*\).*/\2/'

出力:

a;b
c;d
e;f
  • \(^\|.*:\)行の先頭または後にコロンが続くすべての文字と一致します。

答え2

私はこのような状況についてだまされる:前に1つ、最後に1を追加して特殊なケースを削除すると、常に一致します。:a=foo:

だから:

sed -e 's/^/:/' -e 's/$/:/' -e 's/.*:di=\([^:]*\):.*/\1/'

最適化できる

sed -e 's/^\(.*\)$/:\1:/' -e 's/.*:di=\([^:]*\):.*/\1/'

結果:

% echo "di=a;b:*.di=c;d:ddi=e;f" | sed -e 's/^/:/' -e 's/$/:/' -e 's/.*:di=\([^:]*\):.*/\1/'
a;b
% echo "ddi=a;b:di=c;d:*.di=e;f" | sed -e 's/^/:/' -e 's/$/:/' -e 's/.*:di=\([^:]*\):.*/\1/'
c;d
echo "*.di=a;b:ddi=c;d:di=e;f" | sed -e 's/^/:/' -e 's/$/:/' -e 's/.*:di=\([^:]*\):.*/\1/'
e;f

もう一つのチートは改行に変換することです。その後、常に何もせずに:一致します。a=foo:

tr : '\012' | sed -n 's/^di=//p'

答え3

Posixlyは示されているように実行できます。すべてのコロンを新しい行に変換し、di =が表示されるまで先行するKVペアを切り取り続けます。

{
echo "di=a;b:*.di=c;d:ddi=e;f"
echo "ddi=a;b:di=c;d:*.di=e;f"
echo "*.di=a;b:ddi=c;d:di=e;f"
} \
| sed -n 'y/:/\n/;/^di=/!D;P'

di=a;b
di=c;d
di=e;f

答え4

awk代わりに、フィールドsed区切り文字を使用して各レコードを:繰り返し=、見つかったら次のフィールドを印刷しますdi

$ awk -F '[=:]' '{ for (i = 1; i < NF; ++i) if ($i == "di") { print $(i+1); next } }' file
a;b
c;d
e;f

同様に、レコード区切り記号として:=および改行文字を使用します。

$ awk -v RS='[=:\n]' '$0 == "di" { getline; print }' file
a;b
c;d
e;f

awkRSこれは、マルチキャラクタ値を正規表現として扱う場合にのみ機能します。最後のバリエーションも印刷されます。 diそのような値が複数ある場合、元の行の各値(最初のバリアントは次をnext呼び出してこれを防ぎます。

関連情報