'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}'
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:
-F","The field separator is set to a commaFS=" "The field separator is set to a space. This is done after the first line has been read.$0=$3Re-assinging$0with a value (in this case$3) will make gawk split that value again, by theFS.print $5print the 5th field.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 |
