我有一个文件有很多行,但我希望将第五列中前4635行的字符串X
更改为另一个字符串A
,而不会丢失列之间的原始制表符/间距。
我希望改变
ATOM 2732 HN SER X 176 181.410 174.270 311.410 0.00 0.00
ATOM 2733 CA SER X 176 180.170 172.920 310.330 0.00 0.00
ATOM 2734 HA SER X 176 179.860 171.950 310.720 0.00 0.00
ATOM 2735 CB SER X 176 179.010 173.910 310.790 0.00 0.00
ATOM 2736 HB1 SER X 176 178.020 173.710 310.340 0.00 0.00
ATOM 2737 HB2 SER X 176 178.910 173.930 311.900 0.00 0.00
进入
ATOM 2732 HN SER A 176 181.410 174.270 311.410 0.00 0.00
ATOM 2733 CA SER A 176 180.170 172.920 310.330 0.00 0.00
ATOM 2734 HA SER A 176 179.860 171.950 310.720 0.00 0.00
ATOM 2735 CB SER A 176 179.010 173.910 310.790 0.00 0.00
ATOM 2736 HB1 SER A 176 178.020 173.710 310.340 0.00 0.00
ATOM 2737 HB2 SER A 176 178.910 173.930 311.900 0.00 0.00
我想出了以下代码,
awk '{if (NR>=1&&NR<=4635) split($0, a, FS, seps); a[5]="A"; for (i=1;i<=NF;i++) printf("%s%s", a[i], seps[i]); print ""}' dat > tmp
但是文件中的所有行现在似乎在第五列中具有A
而不是1-4635行。任何建议都将不胜感激!
使用GNU awk作为match()
和s/S
的第三个参数缩写:
$ awk 'NR<4636{match($0,/((S+s+){4}).(.*)/,a); $0=a[1] "A" a[3]} 1' file
ATOM 2732 HN SER A 176 181.410 174.270 311.410 0.00 0.00
ATOM 2733 CA SER A 176 180.170 172.920 310.330 0.00 0.00
ATOM 2734 HA SER A 176 179.860 171.950 310.720 0.00 0.00
ATOM 2735 CB SER A 176 179.010 173.910 310.790 0.00 0.00
ATOM 2736 HB1 SER A 176 178.020 173.710 310.340 0.00 0.00
ATOM 2737 HB2 SER A 176 178.910 173.930 311.900 0.00 0.00
或使用任何awk:
$ awk 'NR<4636{match($0,/([^[:space:]]+[[:space:]]+){4}./); $0=substr($0,1,RLENGTH-1) "A" substr($0,RLENGTH+1)} 1' file
ATOM 2732 HN SER A 176 181.410 174.270 311.410 0.00 0.00
ATOM 2733 CA SER A 176 180.170 172.920 310.330 0.00 0.00
ATOM 2734 HA SER A 176 179.860 171.950 310.720 0.00 0.00
ATOM 2735 CB SER A 176 179.010 173.910 310.790 0.00 0.00
ATOM 2736 HB1 SER A 176 178.020 173.710 310.340 0.00 0.00
ATOM 2737 HB2 SER A 176 178.910 173.930 311.900 0.00 0.00
如果您的输入是像示例中所示的固定宽度字段,那么您可以将FIELDWIDTHS
与GNU awk
:一起使用
awk -v FIELDWIDTHS='21 1 *' -v OFS= 'NR<=4635{$2="A"} 1'
这里,第一个字段由21
字符组成,第二个字段为1
字符,其余字段为第三个字段。然后,您可以只更改所需行的第二个字段。
如果输入不是固定宽度,则可以使用sed
或perl
:
# GNU sed
sed -E '1,4635 s/^((S+s+){4})S+/1A/'
# if s and S isn't supported
sed -E '1,4635 s/^(([^[:space:]]+[[:space:]]+){4})[^[:space:]]+/1A/'
perl -pe 's/^(S+s+){4}KS+/A/ if $.<=4635'
添加大括号/大括号和else
分支:
awk '{if (NR>=1&&NR<=4635) {split($0, a, FS, seps); a[5]="A"; for (i=1;i<=NF;i++) printf("%s%s", a[i], seps[i]); print ""} else {print}}' dat > tmp
如果没有大括号/大括号,if
的正文只包含一个split
命令。