我想提取client_id和id后面的数字,并在每一行中配对client_id和id。
例如,对于以下几行日志,
User(client_id:03)) results:[RelatedUser(id:204, weight:10),_RelatedUser(id:491,_weight:10),_RelatedUser(id:29, weight: 20) User(client_id:04)) results:[RelatedUser(id:209, weight:10),_RelatedUser(id:301,_weight:10) User(client_id:05)) results:[RelatedUser(id:20, weight: 10)
我想输出
03 204 03 491 03 29 04 209 04 301 05 20
谢谢
这是一个awk
脚本,它可以工作(我把它放在多行上,使它更加冗长,所以你可以看到发生了什么):
#!/bin/bash awk 'BEGIN{FS="[\(\):,]"} /client_id/ { cid="no_client_id" for (i=1; i<NF; i++) { if ($i == "client_id") { cid = $(i+1) } else if ($i == "id") { id = $(i+1); print cid OFS id; } } }' input_file_name
输出:
03 204 03 491 03 29 04 209 04 301 05 20
说明:
awk 'BEGIN{FS="[\(\):,]"}
:调用awk
,使用(
)
:
和,
作为分隔符来分隔你的字段 /client_id/ {
:只对包含client_id
的行执行以下操作: for (i=1; i<NF; i++) {
:遍历每行一个字段的字段 if ($i == "client_id") { cid = $(i+1) }
:如果我们当前所在的字段是client_id
,那么它的值就是下一个字段。 else if ($i == "id") { id = $(i+1); print cid OFS id;}
else if ($i == "id") { id = $(i+1); print cid OFS id;}
否则,如果我们当前所在的字段是id
,那么将client_id : id
对stdout
到stdout
input_file_name
:提供输入文件的名称作为awk
脚本的第一个参数。 这可能对你有用:
awk -F "[):,]" '{ for (i=2; i<=NF; i++) if ($i ~ /id/) print $2, $(i+1) }' file
结果:
03 204 03 491 03 29 04 209 04 301 05 20
这可能适用于你(GNU sed):
sed -r '/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d;s//\2 \3\n\1/;P;D' file
/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d
如果行没有预期的字符串删除它。 s//\2 \3\n\1/
通过复制client_id
重新排列行,并提前移动第一个id
,从而减少连续迭代的行数。 P
打印到引入的换行符。 D
删除引入的换行符。 我更喜欢awk,但是如果你想知道如何用sed来做这个,那么这里有一个和GNU sed一起工作的方法。
parse.sed
/client_id/ { :a s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/ ta s/^[^\n]+\n// }
像这样运行它:
sed -rf parse.sed infile
或者作为一个单线:
<infile sed '/client_id/ { :a; s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/; ta; s/^[^\n]+\n//; }'
输出:
03 204 03 491 03 29 04 209 04 301 05 20
这个想法是重复匹配client_id:([0-9]+)
和id:([0-9]+)
对,并把它们放在模式空间的末尾。 在每次通过时, id:([0-9]+)
被删除。
最后的替换将循环中的剩余部分删除。