Awk 如何使用vi或sed替换指定字符串之间多次出现的字符?
我试图替换“,”仅当它出现在65510和“I”之间时: 因此,期望的输出是:Awk 如何使用vi或sed替换指定字符串之间多次出现的字符?,awk,sed,replace,between,Awk,Sed,Replace,Between,我试图替换“,”仅当它出现在65510和“I”之间时: 因此,期望的输出是: 2001::/32,fd00::230:5,0,100,0,65510_6939,i 2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i 我尝试了以下方法: sed -e 's/,\([^65510]*\)i/_\1i/' input-file.txt 但输出仅替换最后一个“,”: 请您尝试使用GNUawk中显示的样本编写并
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
我尝试了以下方法:
sed -e 's/,\([^65510]*\)i/_\1i/' input-file.txt
但输出仅替换最后一个“,”:
请您尝试使用GNU
awk
中显示的样本编写并测试以下内容
awk '
match($0,/65510.*i/){
val=substr($0,RSTART,RLENGTH)
gsub(/,/,"_",val)
print substr($0,1,RSTART-1) val substr($0,RSTART+RLENGTH)
}
' Input_file
更一般的回答:如果我们有一次以上的i
出现,并且它可能会或可能不会像65510….i….i
那样出现在系列中,那么我们可以尝试以下内容
awk '
{
line=""
while(match($0,/65510[^i]*/)){
val=substr($0,RSTART,RLENGTH+1)
gsub(/,/,"_",val)
line=(line?line:"")substr($0,1,RSTART-1) val
$0=substr($0,RSTART+RLENGTH+1)
}
if($0!=""){
line=line $0
}
print line
}
' Input_file
这可能适用于您(GNU-sed):
如果当前行包含
65510
,然后是i
,则将它们之间的任何,
替换为。使用sed
可以使用循环:
[步骤101]$cat文件
2001::/32,fd00::230:5,0100,0655106939,i
2001:200:900::/40,fd00::230:50100,06551069392516766076607660,i
[步骤102]$
[步骤103]$sed-e:loop-e的s/\(,65510.*\),\(*,i\)/\1\u2/;tloop'文件
2001::/32,fd00::230:5,0100,065510_6939,i
2001:200:900::/40,fd00::230:50100,065510_6939_2516_7660_7660_7660,i
[步骤104]$
[步骤105]$#如果您的sed支持-E,那么它可以简单一点--
[步骤106]$sed-E-E:loop-E's/(,65510.*),(.*,i)/\1_2/;tloop'文件
2001::/32,fd00::230:5,0100,065510_6939,i
2001:200:900::/40,fd00::230:50100,065510_6939_2516_7660_7660_7660,i
关于t
命令:
t
标签
如果自读取最后一个输入行以及自最后一个t
或t
命令,然后分支到标签;若省略了标签,则分支到脚本的末尾
您可以使用cool sed调试工具查看其工作原理:
第三个参数的GNU awk匹配()和GESUB():
上面只将每个输入行分成3部分(部分直到65510
前面的逗号,部分从65510
直到i
前面的逗号,以及行的其余部分),然后替换每个,
在中间部分粘贴。
并将3个部分粘贴在一起,形成修改后的输出行。如果输入行不包含,65510.*,i
,则保持原样
如果输入中可以存在、65510x、.*、i
(其中x
是任何非逗号的字符),则会失败-如果可以,请将其包含在问题的示例中。您可以尝试Perl
$ cat lou.txt
2001::/32,fd00::230:5,0,100,0,65510,6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510,6939,2516,7660,7660,7660,i
$ perl -pe ' s/65510\K(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;$c/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
或
如果您确定65510之前始终有一个逗号,那么
$ perl -pe ' s/,(?=65510)(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;sprintf(",%s",$c)/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
如果65510两边都用逗号包裹,则
$ perl -pe ' s/,(?=65510,)(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;sprintf(",%s",$c)/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
如果65510作为不同字符串的一部分出现,例如165510
,则该操作将失败。我知道OP没有说清楚,但他们的代码以/,65510…
开头,所以我怀疑这是他们真正想要匹配的。还要注意的是,在输出中将,
之前的,
替换为。
是最接近于使用“sed”解决问题的方法。从这一点开始,我可以很容易地清理“_I”。非常感谢,艾德,说得好。但就我而言,“65510”总是正确的。所以,“65510”总是出现在整个文件中。pynexj的解决方案对我来说非常有效。谢谢。如果65510作为其他字符串的一部分出现,例如165510
,则该操作将失败。我知道OP没有说清楚,但他们的代码以/,65510…
开头,所以我怀疑这是他们真正想要匹配的。它还不希望在输出中将,
之前的,
替换为。@EdMorton,当然,谢谢您的输入,先生。我考虑过一个案例,没有考虑过这个角落的案例。这就是为什么我通常根据显示的示例写这行代码。先生,在我做完我的烹饪和晚餐后,我将尝试讨论这一点。您应该在示例输入/输出中包括一些非平凡的案例,包括、165510、foo、I
、、655101、foo、I
、、65510、foo、65510、bar、I
、以及foo、65510、,我
因为匹配您想要的字符串总是很容易的,但是不匹配您不想要的字符串要困难得多!考虑到其中一些输入(可能还有我没有提到的其他输入),所有当前发布的解决方案都将失败。@EdMorton谢谢,修改了解决方案以考虑您的问题,我实际上误读了,我将尝试的与期望的部分混淆。和往常一样,OP指定和期望的内容可能不同,因此我总是用“可能”这个词来限定我的解决方案。
$ awk 'match($0,/(.*,)(65510.*)(,i.*)/,a){$0=a[1] gensub(/,/,"_","g",a[2]) a[3]} 1' file
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$ cat lou.txt
2001::/32,fd00::230:5,0,100,0,65510,6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510,6939,2516,7660,7660,7660,i
$ perl -pe ' s/65510\K(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;$c/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
$ perl -pe ' s/(?=65510)(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;$c/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
$ perl -pe ' s/,(?=65510)(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;sprintf(",%s",$c)/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$
$ perl -pe ' s/,(?=65510,)(.+?)(?=,i)/$c=$1;$c=~s!,!_!g;sprintf(",%s",$c)/ge ' lou.txt
2001::/32,fd00::230:5,0,100,0,65510_6939,i
2001:200:900::/40,fd00::230:5,0,100,0,65510_6939_2516_7660_7660_7660,i
$