使用 sed 将双下划线的完全匹配替换为字符串

replace an exact match for a double underscore with a string using sed

我正在尝试用字符串替换双下划线的精确匹配。

sed -i 's/\<__\>/.abc.def__/g' file

但这会使文件保持不变。感谢任何指点。 从 Sed match exact

跟进

如果您没有重叠匹配项(并且您提供的输入有 none),像这样的 sed 可以:

sed -E  's/([^_]|^)__([^_]|$)/.abc.def__/g' file > newfile

此处,([^_]|^)__([^_]|$) 匹配并捕获到第 1 组 (</code>) 中除 <code>_ 或字符串开头 (([^_]|^)) 之外的任何字符,然后匹配 __,然后将 _ 以外的任何字符或字符串结尾 (([^_]|$)).

捕获到第 2 组 (</code>) <p>如果可以有重叠匹配,<code>sed在这里就变得相当难用了。一个完美的替代方法是使用

perl -pe 's/(?<!_)__(?!_)/.abc.def__/g' file > newfile
perl -i -pe 's/(?<!_)__(?!_)/.abc.def__/g' file

(?<!_)__(?!_) 正则表达式包含两个环视,(?<!_) 否定后视,确保当前位置左侧没有 _ 字符,(?!_)负先行确保当前位置右侧没有 _ 个字符。

the online demo:

#!/bin/bash
s='AFM_7499_190512_110136_001_p_EQ4H_1_s60_0012__386___Day_'

sed -E  's/([^_]|^)__([^_]|$)/.abc.def__/g' <<< "$s"
# => AFM_7499_190512_110136_001_p_EQ4H_1_s60_0012.abc.def__386___Day_
perl -i -pe 's/(?<!_)__(?!_)/.abc.def__/g' <<< "$s"
# => AFM_7499_190512_110136_001_p_EQ4H_1_s60_0012.abc.def__386___Day_

这可能对你有用 (GNU sed):

sed -E 's/^/\n/;:a;ta;s/\n__($|[^_])/.abc.def__\n/;ta;s/\n(_+|[^_]+)/\n/;ta;s/\n//' file

在当前行前添加一个换行符。

通过使用换行符作为分隔符的行进行模式匹配。

如果模式匹配,替换为所需的字符串并将分隔符放在替换上。

否则,沿线移动分隔符并重复。

在行尾,删除引入的换行符。


选择:

sed -E 's/(^|[^_])__($|[^_])/\n/g;s//\n/g;s/\n/.abc.def__/g' file