如何用增量数字替换匹配行中的所有第一次出现?

如何用增量数字替换匹配行中的所有第一次出现?

我有一个这样的文件

...
1562 first part
1563 H     col3 H col4
1564 H     col3 H col4
...
3241 H     col3 H col4
3242 third part
...

我只想将H每行中的第一行替换为H##其出现次数。输出应该是:

...
1562 first part
1563 H1    col3 H col4
1564 H2    col3 H col4
...
3241 H1652 col3 H col4
3242 third part
...

到目前为止,我已经尝试过:

max=`grep -c ' H ' b`
while [[ "$i" -le $max ]];do
  grep -m $i ' H ' b|tail -n1|sed "s/H/H$i/1"
  let i=i+1
done

这段代码很慢,它需要读取每一行来替换,并且无法添加文件的第一部分和第三部分。有没有更好的方法来做到这一点?也许 awk ?谢谢。

答案1

例如,您可以使用这个:

$ awk '/H/{sub("H", "H"++v)}1' file
1562 first part
1563 H1     col3 H col4
1564 H2     col3 H col4

3241 H3     col3 H col4
3242 third part
...

这会查找包含这些行并将其与我们不断递增的变量一起H替换。请注意,如果您想在所有匹配的模式中而不是仅在一个模式中执行此更改,则可以使用而不是。HHgsub()sub()

最后一个1是 true 条件,因此它执行默认的 awk 操作:{print $0},即打印整行。

答案2

尝试这个:

  awk 'BEGIN { hNum = 1; } { if ($2 == "H") { $2 = "H" hNum; hNum++; } print $0; }' yourFile > outFile

awk使用空格作为分隔符运行,$2每行的第二个标记也是如此,如果$2等于“H”,则将其替换为“H”,后跟从 1 开始的数字。最后打印出该行。

答案3

perl

perl -pe 's/\bH\b\K/++$i/e' file

您可以将-pe其替换-pi.back -e为就地编辑,将原始文件另存为file.back-pi -e不进行备份。

答案4

{   nl -bpH -w1 |
    sed 's/^\([0-9]*\)[ \t]*\([^H]*.\)/\2\1/'
} <<\DATA
...
1562 first part 
1563 H     col3 H col4
1564 H     col3 H col4
...
3241 H     col3 H col4
3242 third part
DATA

输出

...
1562 first part 
1563 H1     col3 H col4
1564 H2     col3 H col4
...
3241 H3     col3 H col4
3242 third part

这是我能想象的最快的方法——尤其是对于一个非常大的文件。nl仅对包含字符串的行进行编号H并在行首插入该数字,后跟一个<tab>字符。它将所有其他行缩进一些空格。

sed通过管道传递nl的输出|sed然后替换以下序列:

  • 行首出现 0 个或多个数字(引用为\1
  • 0个或多个<tab><space>字符
  • 0 个或多个非 H 字符然后 1 个字符(引用为\2

...和\2\1​​。

所以不包含的行H接受这种治疗:

^''   .*.$ = ^.*.''$

那些确实得到这个的人:

^(digit)*<tab>(not H)*H.*$ = ^(not H)*H(digit)*.*$

...其中''有一个空字符串。

为了获得最大的可移植性,您应该将\tin替换[ \t]为文字<tab>字符。

相关内容