'AWK, 2 prints with different separators from the same file

Lets say I have this line

"58062","2022-03-23 10:07:21.718670","Standard query 0x04c0 AAAA contoso.local"

And I just want to print "contoso.local" which is the 5th column from the last block inside double quotes.

I get what I want by doing this:

cat file.log | awk -F "," '{print $3}' | awk '{print $5}'

Is there a more elegant way of achiving this? I've tried an awk inside the first awk but that does not work, I believe I am using GNU Awk that comes in Ubuntu 18.

EDIT:

This indeed is a log file (lots of filtered dns queries) where all lines have the same structure, to be more specific: I don't strictly need the last word from the line, I could for example need to extract the alphanumeric code right before the domain, it would always be the 3th column of the last block.

"58062","2022-03-23 10:07:21","Standard query 0x04c0 A contoso.local"
"58063","2022-03-23 10:08:22","Standard query 0xcif0 A something.local"
"58064","2022-03-23 10:09:23","Standard query 0xEec0 AAAA domain.local"

For the file above this works:

cat file.log | awk -F "," '{print $3}' | awk '{print $4}'
awk


Solution 1:[1]

Answer from @JNevill in the comments above

awk -F"," '{split($3,a,"[  \"]"); print a[5]}' test.txt

Solution 2:[2]

Another option is simply to use sed with the usual substitution for ('s/find/replace/' file) capturing the last whitespace separated text in the line up to the first '"' and reinserting that text using the first named backreference.

sed -E 's/^.*[[:space:]]([^"]+)"$/\1/'

The -E option above specifies Extended Regular Expression syntax. If your sed doesn't support -E (or -r), you simply have to state the match a 2nd time with * (zero or more occurrences) and escape the parenthesis in the capture-group. With Basic Regular Expression that would be:

sed -E 's/^.*[[:space:]]\([^"][^"]*\)"$/\1/'

Example Use/Output

With your example line in file, you would get:

$ sed -E 's/^.*[[:space:]]([^"]+)"$/\1/' file
contoso.local

Solution 3:[3]

Some clarification on my comment:

gawk -F"," '{ FS=" "; $0=$3; print $5 }' file.log

This will work when file.log only has one line, and not when it contains multiple lines. This can be fixed by doing:

gawk -F"," '{ FS=" "; $0=$3; print $5; FS="," }' file.log

In steps:

  1. -F"," The field separator is set to a comma
  2. FS=" " The field separator is set to a space. This is done after the first line has been read.
  3. $0=$3 Re-assinging $0 with a value (in this case $3) will make gawk split that value again, by the FS.
  4. print $5 print the 5th field.
  5. FS="," Set the field separator back to a "," to process the next line.

Because of this assigning values to FS multiple times, it is probably better to use split()

This will lead to:

gawk -F"," '{ split($3,a," "); print a[5] }' file.log

(As also given by JNevil in the comments)

Solution 4:[4]

It depends on your data. If the question is: 'Print the last "word" without ending quote', then maybe:

sed -E 's/.* (.*)"/\1/'
awk -F'.* |"' '{$0=$2}1'

Solution 5:[5]

# grep -oP '([^\s]+)(?="$)' file.log 
contoso.local
something.local
domain.local

1.grep has lookaround support?you need add -P option to your grep (if your grep supports it). since PCRE supports them.

2.\s matches any whitespace, ^ Indicates negation, + Indicates matching one or more times?"$ means ending with a quotation mark

Solution 6:[6]

If you're VERY certain whatever you need is after the last space/tab of $3, then something like

      # using FS to deal with trailing double-quote
 
      mawk 'sub("^.+ ",_,$(($!_=$_=$3)<_))' FS=',|["]$'
or
      # using gsub() to deal with trailing double-quote
 
      mawk 'gsub("^.+ |["]$",_,$(NF=($_=$3)~_))' FS=','
or
      #using RS to deal with trailing double-quote
 
      mawk 'sub("^.+ ",_,$(NF=($_=$3)~_))' FS=',' RS='"?\n' 


"58062","2022-03-23 10:07:21","Standard query 0x04c0 A contoso.local"
"58063","2022-03-23 10:08:22","Standard query 0xcif0 A something.local"
"58064","2022-03-23 10:09:23","Standard query 0xEec0 AAAA domain.local"

contoso.local
something.local
domain.local

or perhaps

 echo "${aaa}" \
 \
 | mawk 'BEGIN { FS=_="," 
   
   } $!+_=$+(FS=_)=substr("",$(($!+_=$3)<"")=$+(FS=" |[\42]$")) $--NF'  

contoso.local
something.local
domain.local

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 darko
Solution 2 David C. Rankin
Solution 3 Luuk
Solution 4 steffen
Solution 5 mrqiao001
Solution 6