如何用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'
我有这样的记录:
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'