Awk 如何使用vi或sed替换指定字符串之间多次出现的字符?

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中显示的样本编写并

我试图替换“,”仅当它出现在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
但输出仅替换最后一个“,”:


请您尝试使用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
$