我有以下格式的文件
m.dat -c16 -S32m 1.3768702014349401 s, rate: 3.2434134115834929 GB/s.
m.dat -c16 -S64m 1.0852226612623781 s, rate: 4.115062684139847 GB/s.
m.dat -c20 -S1m 3.8889309875667095 s, rate: 1.1483256688332133 GB/s.
m.dat -c20 -S2m 16.622251618420705 s, rate: 0.26866151348562284 GB/s.
m.dat -c20 -S4m 4.5505061785224825 s, rate: 0.98137637927430543 GB/s.
m.dat -c20 -S8m 2.4563963813707232 s, rate: 1.8180124800752873 GB/s.
我想从中提取不同的数字值。特别是,我得到了类似的东西:
m.dat 20 4 4.5505061785224825 0.98137637927430543
也就是说,我想提取数字值,不带字符加上文件中每行的第一个字段。
我可以轻松地使用awk
获取每行的不同字段,但这些值还包括-c
和-S
,这些不感兴趣。
awk '{print $1, $2, $3, $4}' file
答案 0 :(得分:3)
这是一个棘手的perl:
$ perl -lane '@fields=(@F[0], /(\d+(?:\.\d*)?|\d*\.\d+)/g); print "@fields"' file
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
根据要求运行,解释。
答案 1 :(得分:2)
另一个perl
解决方案
$ perl -lne 'print join "\t", /^\s*\K\S+|\d+\.\d+|\d+/g' file
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
join "\t"
使用tab作为输出分隔符,如果需要,将其更改为任何其他字符串序列/^\s*\K\S+|\d+\.\d+|\d+/g
正则表达式定义要提取的文本
^\s*\K\S+
从行的开头,不包括可选空格,获取非空格字符 - 在这种情况下获取行标签m.dat
\d+\.\d+
在.
\d+
顺序很重要,首先提取小数,然后获得非小数位数序列答案 2 :(得分:1)
awk '{print $1,substr($2,3),substr(substr($3,3),1,length(substr($3,3))-1),$4,$7}' file
输出:
m.dat 16 32 1.3768702014349401 3.2434134115834929 m.dat 16 64 1.0852226612623781 4.115062684139847 m.dat 20 1 3.8889309875667095 1.1483256688332133 m.dat 20 2 16.622251618420705 0.26866151348562284 m.dat 20 4 4.5505061785224825 0.98137637927430543 m.dat 20 8 2.4563963813707232 1.8180124800752873
答案 3 :(得分:1)
我建议paste
,cut
,awk
和tr
的实用组合:
$ paste -d' ' <(cut -d' ' -f1 file) <(awk '{print $2, $3, $4, $7}' file | tr -dC '0-9. \n')
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
这不是最快的方法,但很容易理解:
cut -d' ' -f1 file
从文件file
输出第一个以空格分隔的字段。
awk '{print $2, $3, $4, $7 }'
输出file
的以空格分隔的字段2,3,4和7,在输出中以单个空格分隔。
tr -dC '0-9 \n'
从-d
的输出中移除(-C
)除(awk
)个数字,空格和换行符之外的所有字符。 paste -d' ' <(...) <(...)
使用两个process substitutions合并来自cut
命令和awk
管道输出的相应行,由单个空格分隔。< / p>
答案 4 :(得分:1)
通常不会使用用户定义的awk
函数,但在这种情况下,它们允许使用简单,可扩展的解决方案:
$ awk '
function strip(val) { gsub("[^0-9.]", "", val); return val } # keep only digits and "."
{ print $1, strip($2), strip($3), $4, $7 }
' file
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
或者, GNU awk
的{{1}}函数允许相对简洁的解决方案:
gensub()
答案 5 :(得分:1)
我想要最简单的想法和最少的代码奖。如果您想要的只是数字数据,请使用非数字作为分隔符:
$ awk -F '[^0-9.-]+' '{split($0, a, / +/); print a[2], $4, $6, $7, $8}' dat
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
要在第一个字段上添加,请将记录拆分为两种方式。
答案 6 :(得分:0)
我建议去除所有非数字值(仍然需要改进来处理.
):
$ awk '{ for (i=2;i<=NF;i++) { gsub("[^0-9.]*","",$i); } gsub("\\s+", " "); $NF=""; print ; }' data.dat
m.dat 16 32 1.3768702014349401 3.2434134115834929
m.dat 16 64 1.0852226612623781 4.115062684139847
m.dat 20 1 3.8889309875667095 1.1483256688332133
m.dat 20 2 16.622251618420705 0.26866151348562284
m.dat 20 4 4.5505061785224825 0.98137637927430543
m.dat 20 8 2.4563963813707232 1.8180124800752873
编辑:我认为我的附加点(在正则表达式中包含.
时)也是由于第一个字段也被替换了。我已相应地修改了答案。