假设一个input.txt
文件包含多个字符串,如下所示:
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]
我想替换为:
:foo:`a`
:foo:`b`
:foo:`c`
我想我可以用sed
or来达到这个结果rg
(我从未使用过awk
)。
但该文件还包含其他字符串,如下所示:
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]
我想替换为:
:foo:`d <a>`
:foo:`e <b> `
:foo:`f <c>`
我所有的尝试都失败了,因为我不知道如何同时处理两种不同的模式。
您知道一些方法可以实现后一个结果(顺便说一句,前一个结果)吗?
答案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 个独立的部分。首先,我们挤压 ( -s
) 并用 , 替换一些字符tr
,以创建输出的“轮廓”,然后用 ased
我们进行两次单独的替换,一个用于两个字符匹配,一个用于两个字符不同时。
< 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
来管理处理两种给定的格式:
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>`