2013-03-28 108 views
1

我想从我的日志文件中提取<到下一个使用正则表达式提取子字符串

$>cat messages.log 
2013-03-24 19:32:37.231 <F280 [192.168.178.22]:5000 -- Unknown>, Msg:[Test1] 
2013-03-24 19:32:37.547 <F281 [192.168.178.22]:5000 -- Unknown>, Msg:[Test2 
Test3 
Test4] 
2013-03-24 19:32:38.833 <F280 [192.168.178.22]:5000 -- Unknown>, Msg:[Test5] 
2013-03-24 19:32:42.222 <F281 [192.168.178.22]:5000 -- Unknown>, Msg:[Test6] 
$>sed 's/.*\<\(.*\) \[.*/\1|/g' messages.log 
F280| 
F281| 
Test3 
Test4] 
F280| 
F281| 

我几乎得到了我想要的,除了换行符的输出。所以我想得到以下结果:

F280|F281|F280|F281 

正则表达式是怎样的?

回答

2

我不会创建一个不可读的正则表达式要做到这一点我会使用awk这里:

$ awk -F'[< ]' '/^[0-9]+/{s?s=s"|"$4:s=s$4}END{print s}' file 
F280|F281|F280|F281 
+0

到目前为止,它改善了输出效果,效果更好,但如果将其应用于整个日志文件,还会打印更多不需要的值。我对awk并不熟悉,但可能您有一个想法如何解决此消息:“Msg:[Test5 \ n AAA/BBB CCC DDD \ n EEE FFF]”=>这会导致不知怎的,“CCC”! – janr 2013-03-28 12:43:58

+1

那么你可以过滤什么?你想要什么线是独特的?如果他们以'2013'开头'awk -F'[<]''/^2013/{s?s = s“|”$ 4:s = s $ 4} END {print s}'file'就足够了? – 2013-03-28 13:15:37

+0

是的,它做到了,但我将“2013”​​更改为“[0-9] +”!为什么“[0-9] {4}”不能用awk工作? – janr 2013-03-28 14:03:30

1

试试这个:

 
sed -n '/</{s/^.*<\([^ ]\+\) .*$/\1|/g;H;${x;s/\n//g;s/|$//;p}}' messages.log 
0

尝试类似的东西(你会嵌套组),或在正则表达式打开多选项:

(^.+<(\w+) .+$)+ 
0

是否必须只能使用grep或也行吟诗人r命令可用? 我想说的是

grep "<.* " messages.log | sed 's/.*\<\(.*\) \[.*/\1|/g' | tr -d '\n' | sed 's/.$//' 

第一个grep的是删除数据未按照你想要的图案,接着为您的sed命令。 在输出时,谁应该像

F280| 
F281| 
F280| 
F281| 

最后tr命令只是在每行的末尾删除换行符(即它加到结果),而最后的sed只是删除最后一个竖线分隔符

+0

这条管道是过度杀伤。但是'grep -o“<[^] *”file'的一些提示会更好地过滤结果,'sed'不需要做太多的工作。如果你有'GNU grep',那么使用积极的look-behind可以让你得到'grep -Po'(?<= <)[^] *“file',那么需要一些简单的工作来重新格式化'grep - Po“(?<= <)[^] *”file | tr'\ n''|' | sed's/| $ //''但是正如我的回答显示'awk'是一个很好的工具。 – 2013-03-28 11:24:33