
コロンで区切られた作業文字列があり、各形式はa=b
fooを抽出するために解析する必要があります。ここで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
awk
RS
これは、マルチキャラクタ値を正規表現として扱う場合にのみ機能します。最後のバリエーションも印刷されます。各 di
そのような値が複数ある場合、元の行の各値(最初のバリアントは次をnext
呼び出してこれを防ぎます。