用awk在日志文件中的两个字符串之间提取数字
这是一个日志行的示例: 我想查找callee_num:<<"
文本块之后出现的数字,直到下一个>>。使用awk
用awk在日志文件中的两个字符串之间提取数字
2016-08-21T06:37:36.830627+00:00 cccc eservice[9999]: INFO con_pr: user:<<"conxa3">> callee_num:<<"+6182290000648">> sid:<<"xxxxxxxxx160821082523657">> credits:-2.5 result:ok provider:outqtm.ym.ms
2016-08-21T06:37:42.728469+00:00 cccc eservice[32499]: INFO con_end_procr: user:conxa3 callee_num:+6182290000648 sid:xxxxxxxxx160821082523657 duration:725 result:ok provider:outqtm.ym.ms
除外结果应该是只从第一行+6182290000648
。
这是我已经试过,但不起作用:
awk -F 'callee_num:<<" |\"' '{print $2}' filename
什么是正确的解决方案? (感谢)
用sed可以做到这一点,利用-n
默认情况下禁用打印:
sed -n 's/.*callee_num:<<"\([+0-9]*\)">.*/\1/p' file
当模式匹配,双引号之间的部分被捕获并在更换使用,丢弃其余部分。
当然,也可以使用awk太:
awk 'sub(/.*callee_num:<<"/, "") && sub(/">.*/, "")' file
这将打印在两个换人是成功的行。与使用sed的版本不同,它不检查引号之间的部分是否为数字。如果你愿意,你可以在进一步的检查中添加这样的:
awk 'sub(/.*callee_num:<<"/, "") && sub(/">.*/, "") && /^[+0-9]+$/' file
这确保了后两个换人制成,所有你留下的是的+
和数字从0到9
您尝试使用awk的问题是您的字段分隔符可能为"
,这会使第二个字段conxa3
。
只有一个问题在你的sed中,'\ 1'是什么? –
'\ 1'是一个反向引用,它是指在搜索模式中的括号内捕获的第一个组。 –
在你的'sed'命令中使用表达式,你也可以用'match'调用'awk'并说:'awk'匹配($ 0,/ callee_num:> /,res){print res [1]}'文件'。 – fedorqui
grep
与PCRE(-P
):
grep -Po 'callee_num:<<"\K\+\d+' file.txt
sed
随着:
sed -nE 's/.* callee_num:<<"(\+[[:digit:]]+)".*/\1/p' file.txt
随着GNU awk
:
awk 'match($0, /.* callee_num:<<\"(\+[0-9]+)\".*"/, a) {print a[1]}' file.txt
实施例:
% cat file.txt
2016-08-21T06:37:36.830627+00:00 cccc eservice[9999]: INFO con_pr: user:<<"conxa3">> callee_num:<<"+6182290000648">> sid:<<"xxxxxxxxx160821082523657">> credits:-2.5 result:ok provider:outqtm.ym.ms
2016-08-21T06:37:42.728469+00:00 cccc eservice[32499]: INFO con_end_procr: user:conxa3 callee_num:+6182290000648 sid:xxxxxxxxx160821082523657 duration:725 result:ok provider:outqtm.ym.ms
% grep -Po 'callee_num:<<"\K\+\d+' file.txt
+6182290000648
% sed -nE 's/.* callee_num:<<"(\+[[:digit:]]+)".*/\1/p' file.txt
+6182290000648
% awk 'match($0, /.* callee_num:<<\"(\+[0-9]+)\".*"/, a) {print a[1]}' file.txt
+6182290000648
通过给由|
分开的2个字段分隔符,您告诉awk
使用任一个作为分隔符。
所以当awk
查找任何callee_num:<<"
或"
并且由于它"
之前conxa3
这个字符串后再次发现。因此,您的输出将是conxa3
。总之,你awk
命令类似于:
$ awk -F '"' '{print $2}' /tmp/t
conxa3
如果你确信你的字符串将是相同的,可以改为打印$4
:
$ awk -F '"' '{print $4}' /tmp/t
+6182290000648
或者你可以使用的sub
功能如其他答案帖子所述,则为awk
。
另一个AWK:
$ awk '$7 ~ /<<\"/ {gsub(/.*<<"|">>$/, "", $7); print $7}' file
+6182290000648
的被叫号码是在第七场(即awk '{print $7}' file
将输出):
callee_num:<<"+6182290000648">>
callee_num:+6182290000648
如果<<"
在这一领域找到($7 ~ /<<\"/
)截取该字段中的双引号:callee_num:<<"
+6182290000648
“>>
我不明白你为什么使用'gsub'? –
第一次匹配后的'sub'stops,'gsub'没有。你必须从开始和结束截断。在'gsub()'中有两个匹配,用'|'(逻辑OR)分隔。 –
awk '{split($0,a,"callee_num:<<|>>") } {gsub(/"/,"",a[3]);print a[3]}' filename
+6182290000648
嘿,因为在第一行我有'callee_num:
@ fedorqui thx您的评论。我改变了我的问题。 –