Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

What I'm trying to do is quite simple. I'm generating output from tshark and redirecting it to awk with a pipe |. Since tshark gets live data, I want that awk search in every output for a pattern (some MAC addresses that I already have) in the first column in a file ("target.txt") and, if there's a match, awk should output the first and second column from this file.

Example from target.txt:

ab:cd:ef:gh:ij:kl,Me
12:34:56:78:90:10,You
1b:2d:3f:4h:5j:6l,someone

To make it all easier, my tshark output has only 2 columns, and the MAC address column is the second one.

1 line of tshark output is like:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 
           ^^^^- date and MAC are separated by tab!

So if tshark finds 12:34:56:78:90:10, awk will output

12:34:56:78:90:10 -> You

or even better:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You

EDIT #1

Well, I did some tests and find out that tsharks output is separated by tab \t. It's not a big deal, but already a small improvement. The thing is, I got samples from tshark output and tested with Gnoucs answer through a echo command before the pipe | . It worked. Then I changed the echo for tshark and everything stopped working =).

Is it a problem with the live data or something like that? Here's my code until now:

$ tshark -I -i wlan0 -T fields -e radiotap.dbm_antsignal -e wlan.sa | awk -F'[ ,\t]' '
     FNR == NR { a[$1] = $2 }
     ($NF in a) { print $0" -> "a[$NF] }
 ' alvos.txt -

well, it just worked! It was probably a typo. Thanks for all answers!

share|improve this question

3 Answers 3

up vote 5 down vote accepted

Try this:

$ awk -F'[ ,\t]' '
    FNR == NR { a[$1] = $2 }
    ($NF in a) { print $0" -> "a[$NF] }
' target.txt -

Example:

$ awk -F'[ ,\t]' '
    FNR == NR { a[$1] = $2 }
    ($NF in a) { print $0" -> "a[$NF] }
' target.txt -
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 # Ctrl + D here
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You

Explanation

  • -F[ ,\t]: we use comma, space or tab as field separators.
  • FNR == NR { a[$1] = $2 }: FNR == NR only true when processing first file. So with each line in target.txt, we save the second field to an associative array, with the first field (MAC address) is the index.
  • ($NF in a): When reading the input (- after target.txt causes awk reading from input), if the last field is in associative array a, we print the desired result.
share|improve this answer
    
@mikeserv: No, just in my test. In the OP's case, he just have to pipe output of tshark to awk. –  cuonglm Jun 18 at 2:14
    
@mikeserv: that line is user input on stdin from Gnouc, hence the Ctrl+D to signify EOF. –  Justin C Jun 18 at 2:17
    
No, I get it now - with a pipe that's not a problem, but you were reading from the terminal. Thanks, @Gnouc. –  mikeserv Jun 18 at 2:18
    
@DMurta: Fixed. Add \t to field separators. –  cuonglm Jun 18 at 9:30
    
Found that out too! Thanks! Your response is very good, but I've edited my question with the (last?) problem. I know the answer is very close =] –  DMurta Jun 18 at 11:30

If I understand you correctly, either one of these will at least generate your desired output:

${TSHARK} |
sed -n "$(IFS=',
';  printf '/%s/s//& -> %s/p\n' \
        $(cat target.txt)
)"


${TSHARK} | 
sed -n "$(
   sed 's/,/|s||\& -> /
        s/.*/\\|&|p/
   ' <target.txt
)"

I tested this in the following way:

printf 'ab:cd:ef:gh:ij:kl,Me
12:34:56:78:90:10,You
1b:2d:3f:4h:5j:6l,someone' >./target.txt

printf 'Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10' |
sed ...

And this was my output:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You
share|improve this answer
#!/usr/bin/env awk
# filename ~/mac-lookup.awk

function load_mac_list (filename, array) {
    while ((getline line < filename) > 0) {
        split(line, fields, ",");
        array[fields[1]] = fields[2];
    }
    close(filename)
}

BEGIN {
    load_mac_list("target.txt", mac_list);
}

($5 in mac_list) {
    print $0 " -> " mac_list[$5];
    next;
}

{
    print;   # remove this line to avoid printing unmatched lines
}

Here's the brute force approach. Load the target file, then print the mac alias only if the mac address is in the list.

Note in this case, the "target.txt" is hardcoded in the awk script. In Gnouc's answer, you can script the target list filename as desired.

Usage

$ ${TSHARK} | awk -f ~/mac-lookup.awk
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You
Jun 16, 2014 02:55:51.300286010 zy:xw:vu:ts:rq:po
Jun 16, 2014 02:55:51.300286020 ab:cd:ef:gh:ij:kl -> Me
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.