用 awk 和 sed 替换字符的子字符串

用 awk 和 sed 替换字符的子字符串

我有一个包含很长字符串的文件,我想用 Ns 替换它的子字符串。例子:

测试

ABCDABCDABCD

我想用 awk 命令和 sed 将其子字符串替换为所有字母 N,即索引 5 到 8 的所有字符,因此字母 N 的总长度为 4。

输出

ABCDNNNNABCD

我尝试过这样的事情:

awk '{ v=substr($0,5,4); sed -i "s/$v/N/g";print substr($0,1,4)""v""substr($0,9,12)}' test

然而,这个命令似乎给出了这个输出:

ABCDABCDABC

并且没有进行替换

我想在代码中包含从哪里开始替换的索引号(例如,这里是 5)和替换的长度号(这里是 4),所以我可以修改这些数字,以防万一我想从另一个位置开始并进行不同长度的替换,因为实际上,我有一个包含数千个字母的字符串,并且我想替换数百个字符,因此模式替换在我的情况下不起作用

答案1

使用 GNU awk,你可以做

gawk -v start=5 -v end=8 '{
    mid = substr($0, start, end-start+1)
    print substr($0, 1, start-1) gensub(/./, "N", "g", mid) substr($0, end+1)
}' file

或者用 perl

perl -spe 'substr($_, $start-1, $end-$start+1) =~ s/./N/g' -- -start=5 -end=8 file

对于这两种解决方案,我们都使用命令行选项将开始值和结束值传递给程序。这使得在 shell 脚本中更改值变得容易。如果您还需要使替换角色 N 动态化,那么如何做应该是非常明显的。

答案2

如果您有 GNU awk (gawk),您可以设置FIELDWIDTHS根据字符位置将行拆分为字段。这对于 gawk 版本 >= 4.2 中的情况特别方便,它支持“通配符”尾随字段宽度。然后,您可以使用以下命令替换第二个字段中的字符gsub

echo ABCDABCDABCD | ./gawk -v i=5 -v n=4 '
  BEGIN {FIELDWIDTHS = sprintf("%d %d *", i-1, n)} 
  {gsub(/./,"N",$2)} 1
' OFS=""
ABCDNNNNABCD

在旧版本的 gawk 中,您可以*通过为尾随字段选择适当大的最大大小来模拟:

echo ABCDABCDABCD | gawk -v i=5 -v n=4 '
  BEGIN {FIELDWIDTHS = sprintf("%d %d 65536", i-1, n)} 
  {gsub(/./,"N",$2)} 1
' OFS=""
ABCDNNNNABCD

处理固定宽度数据

捕获可选的跟踪数据

答案3

您可以尝试使用以下命令

 echo "ABCDABCDABCD"| sed "s/ABCD/NNNN/2"

输出

ABCDNNNNABCD

答案4

您可以通过使用以下方法来完成此操作,如 POSIX 或 GNU seds 所示

使用 sed 编辑器:

$ L=5 R=8
$ sed -e '
   s/./\n/'"$L"';s//\n/'"$R"';ta
   :a;s/\n\n/NN/;t
   s/\n./N\n/;ta
' ./test

ABCDNNNNABCD

使用 Perl:

perl -lspe '
   my $c = $idxr - (pos()=$idxl-1);
   s/\G.{$c}/"N"x$c/e;
' -- -idxl=5 -idxr=8 ./test

ABCDNNNNABCD

相关内容