4

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!

3 Answers 3

5

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.
6
  • @mikeserv: No, just in my test. In the OP's case, he just have to pipe output of tshark to awk.
    – cuonglm
    Commented Jun 18, 2014 at 2:14
  • @mikeserv: that line is user input on stdin from Gnouc, hence the Ctrl+D to signify EOF.
    – Justin C
    Commented Jun 18, 2014 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
    Commented Jun 18, 2014 at 2:18
  • @DMurta: Fixed. Add \t to field separators.
    – cuonglm
    Commented Jun 18, 2014 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
    Commented Jun 18, 2014 at 11:30
3

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
2
#!/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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .