按参考行格式对齐文本列的AWK实现问题求助
问题描述
有一个以单个空格分隔列的文本文件,示例内容如下:
ATOM 9803 C2' 5AD 303 72.790 69.600 43.700 +0.140 0.00 PROT C 0 ATOM 9804 H2'' 5AD 303 73.450 68.960 44.300 +0.090 0.00 PROT H 0 ATOM 15 HE1 MET 1 110.230 70.830 15.490 +0.090 0.00 PROT H 0 ATOM 16 HE2 MET 1 111.230 72.300 15.480 +0.090 0.00 PROT H 0 ATOM 17 HE3 MET 1 112.070 70.760 15.610 +0.090 0.00 PROT H 0 ATOM 24 CB GLU 2 107.460 66.320 18.200 -0.180 0.00 PROT C 0 ATOM 251 HB1 GLU 2 106.550 65.940 17.700 +0.090 0.00 PROT H 0
需要按照以下参考行指定的列间距整理列:
AAAA 9999 AAAA AAA 999 99.999 99.999 99.999 +9.999 9.99 AAAA A 9
最终期望输出:
ATOM 9803 C2' 5AD 303 72.790 69.600 43.700 +0.140 0.00 PROT C 0 ATOM 9804 H2'' 5AD 303 73.450 68.960 44.300 +0.090 0.00 PROT H 0 ATOM 15 HE1 MET 1 110.230 70.830 15.490 +0.090 0.00 PROT H 0
尝试的AWK脚本无法正常工作,会用参考行内容替换所有原行内容,脚本如下:
reference_line="AAAA 9999 AAAA AAA 999 99.999 99.999 99.999 +9.999 9.99 AAAA A 9" awk -v ref_line="$reference_line" ' BEGIN { OFS = "" } NR == 1 { print; next } { for (i = 1; i <= NF; i++) { if (i == 2) { $i = substr(ref_line, 11, 5) } else if (i == 3) { $i = substr(ref_line, 17, 4) } else if (i == 4) { $i = substr(ref_line, 22, 4) } else if (i == 6) { $i = substr(ref_line, 32, 5) } else if (i == 7) { $i = substr(ref_line, 39, 7) } else if (i == 8) { $i = substr(ref_line, 47, 8) } else if (i == 9) { $i = substr(ref_line, 56, 8) } else if (i == 10) { $i = substr(ref_line, 65, 8) } else if (i == 11) { $i = substr(ref_line, 74, 8) } else if (i == 12) { $i = substr(ref_line, 83) } } print }' out.txt > rearranged_out.txt
解决方案
原脚本错误地用参考行的子串覆盖了原字段内容,正确的做法是根据参考行定义的列宽,将原字段格式化到对应宽度后拼接。以下是修正后的AWK脚本:
awk ' BEGIN { # 参考行对应的格式化模板,每个格式符对应一列的宽度和对齐方式 fmt = "%-6s%-6s%-6s%-5s%-8s%-9s%-9s%-9s%-9s%-8s%-5s%-2s%s\n" } { # 按模板格式化当前行的所有字段 printf fmt, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13 }' out.txt > rearranged_out.txt
脚本说明
- 格式化模板
fmt中的每个%-Ns表示左对齐(-)、占N个字符宽度的字符串:%-6s:对应第1、2、3列,占6字符宽度(含后续空格)%-5s:对应第4列,占5字符宽度%-8s:对应第5、10列,占8字符宽度%-9s:对应第6-9列,占9字符宽度%-5s:对应第11列,占5字符宽度%-2s:对应第12列,占2字符宽度%s:对应最后一列,直接输出内容
- 用
printf按模板输出每行,确保列间距和参考行完全一致。
内容的提问来源于stack exchange,提问作者Gilli
相关产品推荐
相关产品推荐

