input.txt
ファイルに次のような複数の文字列が含まれているとします。
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]
私は次のように変更したい:
:foo:`a`
:foo:`b`
:foo:`c`
私はsed
この結果を使用または達成できると思いますrg
(私はそれを使用したことがありませんawk
)。
ただし、ファイルには次のような他の文字列も含まれています。
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]
私は次のように変更したい:
:foo:`d <a>`
:foo:`e <b> `
:foo:`f <c>`
2つの異なるモードを同時に処理する方法がわからないため、すべての試みは失敗しました。
後者の結果(そして前者の結果)を得るためのいくつかの方法を知っていますか?
答え1
標準sed
構文を使用してください。
sed '
s/^\[\[\(.*\)>\(.*\)|\2\]\]$/:\1:`\2`/; t
s/^\[\[\(.*\)>\(.*\)|\(.*\)\]\]$/:\1:`\3 <\2>`/'
答え2
周囲を見て、周囲の文字列が|
同じであることを確認できます。たとえば、
$ cat ip.txt
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]
# same as: rg -NP '\[\[([^>]+)>([^|]+)\|(?!\2])([^|]+)]]' -r ':$1:`$3 <$2>`'
$ perl -pe 's/\[\[([^>]+)>([^|]+)\|(?!\2])([^|]+)]]/:$1:`$3 <$2>`/' ip.txt
:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`
(?!\2])
|
周囲の文字列が異なることを確認するための否定的な予測アサーションです。
両方を達成するには、代替セクションのフラグでPerlコードを使用できますe
。
$ cat ip.txt
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]
$ perl -pe 's/\[\[([^>]+)>([^|]+)\|([^|]+)]]/":$1:`$3" . ($2 eq $3 ? "`" : " <$2>`")/e' ip.txt
:foo:`a`
:foo:`b`
:foo:`c`
:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`
ここでは、周囲の文字列が同じかどうかによって文字列が選択されます($2 eq $3 ? "`" : " <$2>`")
。|
答え3
これを2〜3つの別々の部分に分けることができるようです。最初に squeeze( -s
) し、一部の文字を に置き換えて出力のtr
「概要」を生成し、次に a を使用してsed
2 つの文字が一致する場合に 1 つと 2 つの文字が一致しないときに 2 つの別々の置換を作成します。
< file tr -s '[<>|]' ':::``' | sed -E 's/(.)`\1`/`\1`/; s/([^:])`(.)`/`\2 <\1>`/'
テスト:
$ cat file
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]
$ <file tr -s '[<>|]' ':::``' | sed -E 's/(.)`\1`/`\1`/;s/([^:])`(.)`/`\2 <\1>`/'
:foo:`a`
:foo:`b`
:foo:`c`
:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`
答え4
awk
与えられた2種類の処理を管理するために使用されます。
awk -F'\\[\\[|\\]\\]|>|\\|' '{
print $1, $2, "`" ($3==$4? $3 : $4" <"$3">") "`";
}' OFS=':' infile
テスト入力:
[[foo>a|a]]
[[foo>bb|bb]]
[[foo>c|ccc]]
[[foo>aaaa|d]]
[[foo>b|ddd]]
[[foo>cccc|fff]]
出力:
:foo:`a`
:foo:`bb`
:foo:`ccc <c>`
:foo:`d <aaaa>`
:foo:`ddd <b>`
:foo:`fff <cccc>`