Romi Kajaki
Romi Kajaki

Reputation: 13

Specific fields using cut or Awk

How to cut a specific field from a line?

The problem is I can't use cut -d ' ' -f 1,2,3,4,5,9,10,11,12,13,14, since the field changes.

Let's say I have a file called /var/log/test, and one of the lines inside the file looks like this :

Apr 12 07:48:11 172.89.92.41 %ASA-5-713120: Group = People, Username = james.robert, IP = 219.89.259.32, PHASE 2 COMPLETED (msgid=9a4ce822)

I only need to get the Username and Time/Date ( please note columns keep changing, that's why I need to match the Username = james.robert and Apr 12 07:48:11

When I use :

grep "james" /var/log/tes | cut -d ' ' -f 1,2,3,4,5,9,10,11,12,13,14 

Doesn't work for me. So it has to match the username and prints only username and data/time. Any suggestions?

Ok so when I use this :

awk -F'[ ,]' '$12~/username/{print $1,$2,$3,$12}' /var/log/test

but it works for some users, but not the others, because fields keep moving.

The sample output of this command is :

Apr 12 06:00:39 james.robert

But when I try this command on this username, it doesn't work. See below :

here is another example that with the above command doesn't show anything:

Apr  8 12:16:13 172.24.32.1 %ASA-6-713228: Group = people, Username = marry.tarin, IP = 209.157.190.11, Assigned private IP address 192.168.237.38 to remote user

Upvotes: 0

Views: 127

Answers (5)

karakfa
karakfa

Reputation: 67467

if your file is structured consistently

awk -F'[ ,]' '{print $1,$2,$3,$12}' file

Apr 12 07:48:11 james.robert

if you need to match the username, using your sample input

$ awk -F'[ ,]' '$12~/james/{print $1,$2,$3,$12}' file
Apr 12 07:48:11 james.robert

UPDATE

OK, your spaces are not consistent, to fix change the -F

$ awk -F' +|,' '{print $1,$2,$3,$12}' file

Apr 12 07:48:11 james.robert
Apr 8 12:16:13 marry.tarin

you can add the /pattern/ to restrict the match to users as above. Note the change in -F option.

-F' +|,' sets the field separator to spaces (one or more) or comma, the rest is counting the fields and picking up the right one to print. /pattern/ will filter the lines that matches the regex pattern, which can > be constrained to certain field only (e.g. 12) by $12~/pattern/

if your text may contain mixed case and you want to be case insensitive, use tolower() function, for example

$ awk -F' +|,' 'tolower($12)~/patterninlowercase/{print $1,$2,$3,$12}' file

Upvotes: 1

Cole Tierney
Cole Tierney

Reputation: 10314

The following perl will print the date and username delimited by a tab. Add additional valid username characters to [\w.]:

perl -ne '
    print $+{date}, "\t", $+{user}, "\n" if
        /^(?<date>([^\s]+\s+){2}[^\s]+).*\bUsername\s*=\s*(?<user>[\w.]+)/
    '

Varying amounts a tabs and spaces are allowed.

Upvotes: 0

jijinp
jijinp

Reputation: 2662

With gawk

awk '{u=gensub(/.*(Username = [^,]*).*/,"\\1","g",$0);if ( u ~ "james") {print u,$1,$2,$3}}' file

Upvotes: 0

sat
sat

Reputation: 14949

With sed:

sed -r 's/^([A-Za-z]{3} [0-9]{1,2} [0-9]{2}:[0-9]{2}:[0-9]{2}).*(Username = [^,]*).*/\1 \2/g' file

Upvotes: 1

JNevill
JNevill

Reputation: 50034

You could use awk to delimit by comma and then use substr() and length() to get at the pieces you care about:

awk -F"," '{print substr($1,1,15), substring($3, 13, length($3)-12)}' /var/log/test

Upvotes: 0

Related Questions