我用来awk '{ gsub(/BAR|WIBBLE/, "FOO"); print }'
替换数据中的文本,例如:
SOMETHING [BAR, WIBBLE]
SOMETHING [BAR]
这给出了所需的结果:
SOMETHING [FOO, FOO]
SOMETHING [FOO]
但现在我必须更新需要替换的文本,如下所示:
awk '{ gsub(/BAR|WIBBLE|ME/, "FOO"); print }'
这会将文本变成:
SOMETHING [ME, WIBBLE]
进入:
SOFOOTHING [FOO, FOO]
如何将我的替换限制为仅括号之间的文本(即保留该文本SOMETHING
)?
编辑
我还需要任何文本的稳健性SOMETHING
(例如SHE GAVE ME THAT
不应替换ME
)。
答案1
一定是这样吗awk
?在其他语言中要容易得多,其中替换的替换部分可以是函数调用。例如perl
:
perl -pe 'sub c{$s=shift;$s=~s/BAR|WIBBLE|ME/FOO/g;$s}s/\[.*?\]/c$&/ge'
答案2
使用 GNU awk,您可以设置括号的内容,然后对(匹配的记录分隔符)RS
进行替换:RT
awk -v RS='\\[[^]]*\\]' '{ gsub(/\<(BAR|WIBBLE|ME)\>/, "FOO", RT); printf "%s%s", $0, RT }' infile
输入文件:
cat << EOF > infile
SHE GAVE ME THAT
SOMETHING [ME, WIBBLE, SOMMER]
EOF
输出:
SHE GAVE ME THAT
SOMETHING [FOO, FOO, SOMMER]
答案3
awk 在正则表达式替换中缺乏反向引用,因此它无法轻松地在上下文中进行替换。 sed 可以做到:
sed -e 's/\(\[[^]]*\)BAR/\1FOO/' 's/\(\[[^]]*\)ME/\1FOO/'
如果您的 sed 支持正则表达式中的交替:
sed -e 's/\(\[[^]]*\)\(BAR\|ME\)/\1FOO/'
即使有后缀,这也仅处理每个括号对内的单个替换,g
因为[^]]*
匹配最长的无闭括号序列。要替换所有这些,请使用显式循环;请注意,这仅在FOO
不是BAR
or的子字符串时才有效ME
。
sed -e ': a' -e 's/\(\[[^]]*\)BAR/\1FOO/' -e 't a' \
-e 's/\(\[[^]]*\)ME/\1FOO/' -e 't a'
如果你需要更复杂的东西,使用perl。
答案4
awk '{ gsub(/\bBAR\b|\bWIBBLE\b|\bME\b/, "FOO"); print }'