我想在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
我知道我需要使用sed或awk。但我不确切知道如何。
由于
答案 0 :(得分:5)
这可能对您有用:
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
答案 1 :(得分:4)
这是一个有效的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;}
:否则,如果我们当前所在的字段为id
,则将client_id : id
对打印到stdout
input_file_name
:提供输入文件的名称作为awk
脚本的第一个参数。答案 2 :(得分:3)
这可能适合你(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
删除引入的换行符。答案 3 :(得分:2)
我更喜欢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]+)
。
最后的替换会从循环中移除遗留物。