我想从日志文件中提取一些信息,其中包含:
...
Running ep. 0
...
...
Initial position for this ep is 7.338690864048985,28.51815509409351,11.795143979909135
...
...
...
Running ep. 1
...
...
Initial position for this ep is 10.599326804010953,7.514871863851674,14.843070346933654
...
...
现在我有一个 bash 代码,可以从中提取一些数据:
cat screen2.dat|grep -oP 'Running ep. \K([0-9]+)|(?<=for this ep is )[+-]?[0-9]+([.][0-9]+)?'|paste -d' ' - -
但输出只是“Running ep”之后的数字。以及“此 ep 的初始位置是”之后的第一个数字
0 7.338690864048985
1 10.599326804010953
.
.
.
我期待类似的事情
0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654
.
.
.
答案1
我认为您过度指定了表达式。您只匹配 substring 之后的单个浮点数for this ep is
。如果你想要该行的其余部分,请使用类似的东西
grep -oP 'Running ep\. \K(.*)|for this ep is \K(.*)' screen2.dat |
paste -d ' ' - -
使用标准sed
,你可以写
sed -n -e 's/^Running ep\. //p' -e 's/.*for this ep is //p' screen2.dat |
paste -d ' ' - -
只需砍掉(用什么都没有替代来删除)行中不需要的部分即可。
您也可以awk
以同样的方式使用,
awk '/^Running ep\. / || /for this ep is / { print $NF }' screen2.dat |
paste -d ' ' - -
或者,一次性格式化所有内容,
awk '/^Running ep\. / { ep = $NF } /for this ep is / { print ep, $NF }' screen2.dat
答案2
您的代码[+-]?[0-9]+([.][0-9]+)?
与点后带有可选数字的单个数字相匹配。如果您想要其中三个,请这样说:([+-]?[0-9]+([.][0-9]+)?,?){3}
但你真正想要的,只需一个sed
脚本即可获得:
sed -e '/Running ep. /{s///;h;}' -e '/.*for this ep is /!d;s///;H;x;s/[\n,]/ /g' screen2.dat
/Running ep. /{...}
{}
是只对匹配的行执行里面的所有内容Running ep.
- 对于这些行,
s///
删除之前匹配的部分并将该行移动到h
旧空间 /.*for this ep is /!d
否 所有与 (!
) 不匹配其他模式的行都可以被d
选择,- 对于其余部分,
s///
只需再次删除模式,将行的其余部分保留为所有数字 H
将此剩余附加到保留空间,我们可以在其中获取 ep 编号x
交换缓冲区,因此我们在保留空间中收集的两个部分现在都在模式空间中,并且s/[\n,]/ /g
用空格替换嵌入的换行符和所有逗号
答案3
withpcregrep
及其M
ultiline 模式:
$ <input pcregrep -M -o{1..4} --om-separator=' ' \
'(?sm)^Running ep\. (\d+)$.*?^Initial position for this ep is ([+-]?\d+(?:\.\d+)?),((?2)),((?2))$'
0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654
但请注意,如果Initial...
特定的 缺少Running ep...
,则.*?
会很高兴地与另一个匹配Running ep...
,并且您最终会在给定的一组值前面得到错误的 ep 编号。
可能更好地用gawk
类似的东西来做到这一点:
<input gawk -v 'FPAT=[+-]?[0-9]+([.][0-9]+)?' '
/^Running ep/ && NF == 1 {ep = $1; next}
/^Initial position for this ep is/ && ep != "" && NF == 3 {
print ep, $1, $2, $3
ep = "" # omit if there can be more than one "Initial position"
# per ep.
}'
其中FPAT
将字段定义为与正则表达式(数字)匹配的字符串,我们只打印一行输出初始位置行,如果有相应的跑步EP线以前见过。
答案4
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ awk '/Running ep/{ep=$NF} /Initial position/{print ep, $NF}' file
0 7.338690864048985,28.51815509409351,11.795143979909135
1 10.599326804010953,7.514871863851674,14.843070346933654
如果您确实想用空格替换这些逗号,那么:
$ awk '/Running ep/{ep=$NF} /Initial position/{gsub(/,/," ",$NF); print ep, $NF}' file
0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654