用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 

什么是正确的解决方案? (感谢)

+0

嘿,因为在第一行我有'callee_num:

+1

@ fedorqui thx您的评论。我改变了我的问题。 –

用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

+0

只有一个问题在你的sed中,'\ 1'是什么? –

+0

'\ 1'是一个反向引用,它是指在搜索模式中的括号内捕获的第一个组。 –

+0

在你的'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 
+0

我需要awk。 thx –

+0

你用'awk'表示这是不可能的吗? @heemayl –

+0

@MaryamPashmi检查我的编辑。 – heemayl

通过给由|分开的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“>>

+0

我不明白你为什么使用'gsub'? –

+0

第一次匹配后的'sub'stops,'gsub'没有。你必须从开始和结束截断。在'gsub()'中有两个匹配,用'|'(逻辑OR)分隔。 –

awk '{split($0,a,"callee_num:<<|>>") } {gsub(/"/,"",a[3]);print a[3]}' filename 
+6182290000648