如何用sed替换特定位置由分隔符分隔的子字符串

How to substitute a substring delimited by separator in a specific position with sed

我有这样的记录:

aaa|11|bcvdgsf|11|eyetwrt|11|kkjdksjk

我会将第二次出现的“11”替换为另一个子字符串,例如 XX。所以输出将是

aaa|11|bcvdgsf|XX|eyetwrt|11|kkjdksjk

我尝试使用这个命令:

#echo "z|11|a|11|b|11|" | sed 's/\(|11\{2\}\)/\|XX/'

但记录没有改变

你可以用它来表示“用 XX:”

替换两侧由单词边界分隔的 11 的第二个实例
$ sed 's/\b11\b/XX/2' <<< 'aaa|11|bcvdgsf|11|eyetwrt|11|kkjdksjk'
aaa|11|bcvdgsf|XX|eyetwrt|11|kkjdksjk

这需要 GNU sed \b 支持。

请尝试我的(可行的)解决方案:

echo "z|11|a|11|b|11|" | sed -r 's/^([a-z]+\|11\|[a-z]+\|)(11)(.+)$/XX/'

如果只匹配整个字段:

$ cat ip.txt
z|11|a|11|b|11|
aaa|11|bcvdgsf|11|eyetwrt|11|kkjdksjk
11|11.2|abc|11|cca
11||11
11|11|ac
a|11|asd|11

$ awk 'BEGIN{FS=OFS="|"}
       {c=0; for(i=1; i<=NF; i++) if($i=="11" && ++c==2) $i="XX"}
       1' ip.txt
z|11|a|XX|b|11|
aaa|11|bcvdgsf|XX|eyetwrt|11|kkjdksjk
11|11.2|abc|XX|cca
11||XX
11|XX|ac
a|11|asd|XX
  • FS=OFS="|" 使用 | 作为输入和输出字段分隔符
  • c=0 为每一行初始化计数器
  • for(i=1; i<=NF; i++) 遍历所有输入字段
  • $i=="11" && ++c==2 如果字段内容恰好是 11,增加计数器并检查它是否是第二个匹配项
  • $i="XX" 根据需要更改字段内容
  • 1 惯用的打印方式 [=20=]

perl 类似的逻辑使用环视来匹配字段边界:

perl -lpe '$c=0; s/(?<![^|])11(?![^|])/++$c==2 ? "XX" : $&/ge'