Pipes for grep and using regular expressions

Basically what I want to do is parse the lines in the file and return the usernames. Usernames are always surrounded by <and>, so I want to use a regular expression to match eveything before (and including) and everything after (including)>, and then invert my match. I understand that grep -vE should do this.

My script looks a bit before this:

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

And test_log consists of the following:

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

However, when running my script, nothing returns, even though when I test the regex in something like regexpal with a backward match, it does exactly what I want. What am I doing wrong?

+5
source share
4 answers

try this grep line:

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.
+11

, @Kent , , , "-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".

+2

I like @Kent better, but if we can accept the recent version of grep and you want to avoid perl-based regular expressions, you can still extract the username directly:

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

You really don't need an external program if your data is as consistent as you show.

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

All Articles