2013-03-01 91 views
4

基本上我想要做的是解析文件中的行并返回用户名。用户名总是被包围在<和>中,所以我想使用正则表达式来匹配之前(包括)<和之后的所有内容(包括),然后反转我的匹配。我知道grep -vE应该能够做到这一点。管道grep和使用正则表达式

我的脚本看起来有点像这样至今:

#!/bin/bash 
while read line; do 
     echo $line | grep -vE '(.*<)|(>.*)' 
done < test_log 

而且test_log由以下部分组成:

Mar 1 09:28:08 (IP redacted) dovecot: pop3-login: Login: user=<emcjannet>, method=PLAIN, rip=(IP redacted), lip=(IP redacted) 
Mar 1 09:27:53 (IP redacted) dovecot: pop3-login: Login: user=<dprotzak>, method=PLAIN, rip=(IP redacted), lip=(IP redacted) 
Mar 1 09:28:28 (IP redacted) dovecot: imap-login: Login: user=<gconnie>, method=PLAIN, rip=(IP redacted), lip=(IP redacted), TLS 
Mar 1 09:27:25 (IP redacted) dovecot: imap-login: Login: user=<gconnie>, method=PLAIN, rip=(IP redacted), lip=(IP redacted), TLS 

但是,运行我的剧本的时候,什么都不会返回,尽管当我用regexpal这样的东西来测试正则表达式,其反向匹配正是我想要的。我究竟做错了什么?

+0

我不明白倒置。 -v意思是“找到这种模式不匹配的行”。我认为更好的方法是简单地捕获用户名。这是否准确? – cmonkey 2013-03-01 17:09:57

回答

11

试试这个grep的行:

grep -Po "(?<=<)[^>]*" 

或更安全:

grep -Po "(?<=user=<)[^>]*" 

编辑

简短说明

-P perl-regex 
-o only matching 
you can get above info from man page 
(?<=foo)bar look-behind assertion. matches bar, only if bar is following foo. 
[^>]* any not > characters. 
+0

好吧,我会的。这样做,我使用最底层的安全性。谢谢。编辑:当谈到正则表达式时,我仍然有点绿。你或其他人可以向我解释一个吗? – Skyline969 2013-03-01 17:13:57

+0

@ Skyline969请参阅编辑回答 – Kent 2013-03-01 17:22:29

+0

谢谢。这就说得通了。 – Skyline969 2013-03-01 17:26:02

1

我一个ctually如@肯特的回答更好,但如果我们可以假设最近的grep的版本,并且要避免基于Perl的正则表达式,你仍然可以提取直接的用户名:

echo $line | grep -o '<[^>]*>' | grep -o '[^<>]*' 
+0

为什么要避免Perlish正则表达式? – 2013-03-01 17:15:23

+2

由于manpage中的注释:'这是高度实验性的,grep -P可能会警告未实现的功能。 – 2013-03-01 17:47:32

0

你并不真的需要一个外部程序如果你的数据和你展示的一样一致的话。

while read line; do 
    line="${line#*user=<}" # Remove from left up to < 
    line="${line%%>*}"  # Remove to right from > 
    echo $line 
done < test_log 
2

其实,我喜欢@肯特的答案也和它是正确的,但有时很难记住像“-Po”的“grep”效用开关。通常,如果你不记得确切的标志你可能会问grep工具来唤醒你的记忆的方式如下:

$ grep --help | grep regex 
    -E, --extended-regexp  PATTERN is an extended regular expression (ERE) 
    -G, --basic-regexp  PATTERN is a basic regular expression (BRE) 
    -P, --perl-regexp   PATTERN is a Perl regular expression 
    -e, --regexp=PATTERN  use PATTERN for matching 
    -w, --word-regexp   force PATTERN to match only whole words 
    -x, --line-regexp   force PATTERN to match only whole lines 

正如我们所看到的,也有另一种可能的选择,如“-E”