替换括号之间的文本

替换括号之间的文本

我用来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不是BARor的子字符串时才有效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 }'

相关内容