我有一个这样的文件
...
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
替换。请注意,如果您想在所有匹配的模式中而不是仅在一个模式中执行此更改,则可以使用而不是。H
H
gsub()
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)*.*$
...其中''
有一个空字符串。
为了获得最大的可移植性,您应该将\t
in替换[ \t]
为文字<tab>
字符。