16

基本的に私がやりたいことは、ファイル内の行を解析してユーザー名を返すことです。ユーザー名は常に < と > で囲まれているため、正規表現を使用して < の前 (を含む) のすべてと、> の後 (および含む) のすべてを照合し、一致を反転させたいと考えています。grep -vE でこれができるはずだと理解しています。

これまでのところ、私のスクリプトは次のようになります。

#!/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 のようなもので逆一致を使用して正規表現をテストしても、まさに私が望んでいることを実行します。私は何を間違っていますか?

4

4 に答える 4

28

この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.
于 2013-03-01T17:08:07.593 に答える
0

データが示すように一貫性がある場合、外部プログラムは実際には必要ありません。

while read line; do
    line="${line#*user=<}"  # Remove from left up to <
    line="${line%%>*}"      # Remove to right from >
    echo $line
done < test_log
于 2013-03-01T19:18:43.783 に答える