考虑这个sample.txt:
ATO N X B
AT H1 X BT
ATOM H25 X BAA
ATOM H3 X BUTZ
ATOM CA X BAT
我想将第 2-4 行中的 X 替换为 awk 或其他内容的“A”,因此输出应该是:
ATO N X B
AT H1 A BT
ATOM H25 A BAA
ATOM H3 A BUTZ
ATOM CA X BAT
我强调 X(或其替代品 A)是行中的第 11 个“实体”(包括字符或空格),并且应在输出中保留第 11 个“实体”,并且所有其他“实体”应保留在原始文件中的位置。
这个怎么做?谢谢
答案1
和awk
:
awk 'BEGIN{ OFS=FS="" } FNR>=2 && FNR<=4 && $11=="X"{ $11="A" }1' sample.txt
使用空字符串作为输入和输出字段分隔符,如果该字段包含 ,则将第 11 个字段替换为输入文件的定义记录号X
。然后打印记录。
答案2
一个简单的sed
命令就可以完成这项工作:
sed '2,4s/ X / A /' your_file
cat foo.txt
ATO N X B
AT H1 X BT
ATOM H25 X BAA
ATOM H3 X BUTZ
ATOM CA X BAT
sed '2,4s/ X / A /' foo.txt
ATO N X B
AT H1 A BT
ATOM H25 A BAA
ATOM H3 A BUTZ
ATOM CA X BAT
正如 @Quasimodo 指出的,sed
如果上面的命令遇到另一个像X
That's a GNU Awk 解决方案这样的序列,它就会失败:
awk 'NR >= 2 && NR <= 4 && $3~/X/ { sub(/X/, "A") } { print }' foo.txt
更新
非常感谢 @Quasimodo 这个命令:
sed '2,4s/^\(.\{10\}\)X/\1A/'
这确保只有第 11 个字符中出现的 X 才会被替换
答案3
使用awk,不一定是GNU,我们如图所示。首先根据范围选择行,然后通过尝试在第 11 个字符位置进行替换来进一步细化它们。
awk '(NR==2),(NR==4) {
sub(/^.{10}X/, substr($0,1,10) "A")
}1' file
同样的事情在珀尔
perl -lpe 'substr($_,10,1) =~ s/X/A/ if 2..4' file
sed -e '
2,4s/./&\n/11
s/X\n/A/;s/\n//
' file
输入:
cat - <<\! > file
ATO N X B
AT H1 Q BT
ATOM H25 X BA
ATOM H3 X
ATOM CA X BAT
!
结果:
ATO N X B
AT H1 Q BT
ATOM H25 A BA
ATOM H3 A
ATOM CA X BAT
答案4
awk 'NR >1 && NR <5 {gsub("X","A",$3)}1' filename
输出
ATO N X B
AT H1 A BT
ATOM H25 A BAA
ATOM H3 A BUTZ
ATOM CA X BAT