2

I want to extract the essid in a dump file from airodump-ng using grep. The part where I want to extract looks like this:

    <SSID first-time="Wed Feb 25 07:06:57 2015" last-time="Wed Feb 25 07:14:23 2015">
        <type>Beacon</type>
        <max-rate>54.000000</max-rate>
        <packets>3371</packets>
        <beaconrate>10</beaconrate>
        <encryption>WPA2 AES-CCM </encryption>
        <essid cloaked="false">WLAN-123651234</essid>
    </SSID>
    <BSSID>24:65:11:3A:68:02</BSSID>
    <manuf>Unknown</manuf>
    <channel>1</channel>
    <freqmhz>2412 23193</freqmhz>
    <maxseenrate>54000</maxseenrate>
    <packets>

So I want to extract the essid "WLAN-123651234" in line 7. How do I do this ? And it shouldn't matter how long the essid is because i want to use that way not only for that essid, so it needs to be extracted like this:

grep >....< dumpfile.netxml
Output: WLAN-1234651234
1
  • 1
    Why not using a xml parser?
    – Braiam
    Feb 28 '15 at 17:46
4

With GNU grep linked to a recent version of the PCRE library (Perl Compatible Regular Expressions), you could try:

$ grep -oP '<essid\b[^<>]*>\K[^<>]*(?=</essid>)' file
WLAN-123651234

This would extract the contents of essid tag.

Explanation:

  • <essid matches exactly the string <essid

  • \b called word boundary which matches between a word character and a non-word character, vice-versa.

  • [^<>]* negated character class which matches any character but not of < or >, zero or more times.

  • \K discards the all the previously matched characters from printing at the final.

  • [^<>]* negated character class which matches any character but not of < or >, zero or more times.

  • (?=</essid>) Positive lookahead assertion which asserts that the match must be followed by the string </essid>.

3
  • Oh yeah thank you, it works perfectly for what I´m trying.
    – Nroh
    Feb 28 '15 at 10:23
  • 1
    "I have a problem with xml parsing. I know! I'll use perl regular expressions. Now I have 2 problems"
    – pqnet
    Feb 28 '15 at 11:38
  • @pqnet Related: stackoverflow.com/questions/1732348/…
    – Kroltan
    Feb 28 '15 at 15:53
4

Why are you using grep to get stuff out of xml-files? You're using grep, so you're probably on a Linux or BSD system, so why not just use xpath from the command line instead?

xpath -q -e "SSID/essid/text()" /path/to/file.xml

Will do precisely what you want, and with far less hassle than a regular expression which tend to be rather fragile in getting stuff out of XML.

If it's not installed, your package manager should be able to take care of it. On Ubuntu the relevant package is called libxml-xpath-perl.

2

With GNU grep:

grep -oP 'essid.*>\K.*(?=<)' file

Output:

WLAN-123651234
2
  • One question to this method: Lets say in the file there are more than one match, so for example the output of grep would be something like this 1 WLAN-1234 2 WLAN-1231 .....how can i get the second line or the third... so only that line ?
    – Nroh
    Mar 1 '15 at 20:03
  • With GNU sed: add | sed -n 2p for second line.
    – Cyrus
    Mar 1 '15 at 20:10
1

At risk of sounding like a broken record - XML is a data structure, and there's a variety of things that can be done to this data structure that are valid as far as the XML spec goes, but that completely break it as far as regular expressions go. Things like line formatting, indendation, wrapping of tags etc.

So I strongly urge anyone - when processing XML - to use an XML parser. These are designed to handle the nesting and processing of XML that ignores format but still differentiates important semantics like tags, nesting and attributes.

So I would approach your problem like this:

#!/usr/local/bin/perl

use strict;
use warnings;
use XML::Twig;

XML::Twig->new(
    'twig_handlers' => {
        'essid' => sub { print $_ ->text }
    }
)->parse( <> );

This will spit out:

WLAN-123651234

And if you're keen to not have a separate script file (but I think you should, because it's generally better for clarity and maintenance) you can reduce further as:

perl -MXML::Twig -e 'XML::Twig->new( twig_handlers => { essid => sub { print $_ -> text,"\n" } } ) -> parse ( <> );' 

For bonus points - you can use xml xpath expressions like:

essid[@cloaked="false"] 

To print a subset.

Usefully too - XML::Twig module comes with the very useful xml_grep utility that ... does exactly what you want, in that it'll grep xml.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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