我有大约 100 个名为 *.txt 的文本文件,格式如下:
=========================================================
rho_center e_center Mass Mass_0 R_e
1.0000e-03 1.1236e-03 1.5379e+00 1.6522e+00 1.0734e+01
J T/W Omega Omega_Kepler axes_ratio
0.0000e+00 0.0000e+00 0.0000e+00 3.5265e-02 1.0000e+00
J/M^2
0.0000e+00
=========================================================
yy| rhoc = 1.00000000e-03 ;
yy| rp_re = 1.00000000e+00 ;
yy| A_diff= 1.00000000e+00 ;
yy| Re = 1.07336268e+01 ;
yy| M0 = 1.65219709e+00 ;
yy| M = 1.53786062e+00 ;
yy| W = 2.10814073e-01 ;
yy| T = 0.00000000e+00 ;
yy| J = 0.00000000e+00 ;
yy| beta = 0.00000000e+00 ;
yy| M_R = 1.43275023e-01 ;
| === periods in msecs ==========
yy| Pa = inf ;
yy| Pe = inf ;
yy| td = 8.46677695e-01 ;
yy| PK = 8.77582921e-01 ;
yy| MDIV = 301 ; SDIV = 601;
我想将 rhoc 和 M 的值连接在一个文本文件中,如下所示:
rhoc M
0.001 1.537
... ...
0.004 2.328
我是 bash 的外行,我尝试使用 awk 来做到这一点,但失败了。如何编写 bash 脚本来完成这项工作?
答案1
对于,假设每个文件gawk
只有一个rhoc
/ :M
gawk '
BEGIN {print "rhoc M"}
BEGINFILE {delete field}
$3 == "=" {field[$2] = $4}
ENDFILE {
if (("rhoc" in field) && ("M" in field))
print field["rhoc"], field["M"]
}' ./*.txt
这将按照文件名的字典顺序处理文件。如果使用zsh
,则替换./*.txt
为./*.txt(n)
,以便顺序为数字(file2.txt
因此前 file10.txt
例如)。
答案2
对于非 gawk 使用(在 linux (mawk) 和 FreeBSD 上测试),请尝试
LC_ALL=C awk -vHD="rhoc M" '
BEGIN {for (MX=m=split(HD, IX); m; m--) FLDS[IX[m]]
print HD
}
FNR == 1 {CNT++
}
$2 in FLDS {OUT[$2, CNT] = $4+0
}
END {for (i=1; i<=CNT; i++) {for(j=1; j<=MX; j++) printf "%.6g%s", OUT[IX[j],i], (j==MX?ORS:OFS)}
}
' *.txt
rhoc M
0.001 1.53786
它将允许您通过简单地预先扩展 HD 变量来扩展数据提取。它对输入文件进行计数,将每个文件所需的数据收集到 OUT 数组中,并在 END 部分中按照遇到的文件的顺序打印所有数据。
答案3
sed
:
sed -n '/rhoc/{s/^yy| rhoc *= *\([0-9.e+-]*\) *;/\1/;h;};/ M /{s/^yy| M *= *\([0-9.e+-]*\) *;/\1/;x;G;s/\n/ /p}' sample
以多行方式:
sed -n '
/rhoc/{
s/^yy| rhoc *= *\([0-9.e+-]*\) *;/\1/
h
}
/ M /{
s/^yy| M *= *\([0-9.e+-]*\) *;/\1/
x;G;s/\n/ /p
}
' sample