4

What would be the most handy way to grab the mouse's mac address from the following output:

~ ➜ bt-device --list
Added devices:
Logitech K811 (00:1F:20:EB:06:E0)
Plattan ADV Wireless (5C:EB:68:1F:D1:62)
Bluetooth Mouse M336/M337/M535 (34:88:5D:3F:1B:88)

Is there something shorter than this:

bt-device --list | grep Mouse | sed -e 's/^.*(\(.*\))$/\1/'
34:88:5D:3F:1B:88

I'm looking for a syntax like:

bt-device --list | grep Mouse | xyztool '(' ')'
1
  • Remove the grep and yours is as good a choice as the others. bt-device --list | sed -e 's/^.*Mouse.*((.*))$/\1/' you could set this as an alias or function in .bashrc if you use it frequently; or just export the regex as an env variable - thats pretty common for regexs for IP addresses, urls, etc.
    – Argonauts
    May 16 '16 at 6:17
7

Use awk to match the line and split it into words separated by ( or ). Take the 2nd word $2, or preferably the next-to-last $(NF-1) if you might have parentheses in the device name:

awk -F '[()]' '/Mouse/{print $(NF-1)}'
2
  • @Jander That's a good point. I've updated the answer. thanks.
    – meuh
    May 16 '16 at 14:33
  • 1
    @TomFenech oops. I should have copied my test script instead of just editing the answer. Thanks.
    – meuh
    May 18 '16 at 13:05
2

Using grep with PCRE (-P):

bt-device --list | grep -Po 'Mouse\s.*?\(\K[^)]+'
  • Mouse\s.*?\( will match Mouse in the line and then upto first (, \K will discard the match

  • [^)]+ will get us the desired portion i.e. characters upto the next )

Example:

$ cat file.txt
Added devices:
Logitech K811 (00:1F:20:EB:06:E0)
Plattan ADV Wireless (5C:EB:68:1F:D1:62)
Bluetooth Mouse M336/M337/M535 (34:88:5D:3F:1B:88)

$ grep -Po 'Mouse\s.*?\(\K[^)]+' file.txt
34:88:5D:3F:1B:88
0

A few more choices:

  1. Perl

    $ bt-device --list | perl -lne 'print $1 if /Mouse.*\((.*)\)/' file 
    34:88:5D:3F:1B:88
    

    In many tools that deal with regular expressions, parentheses (()) are used to capture the matched pattern in a way that can later be used. In Perl, the 1st such captured pattern is $1, the second $2 etc. Here, we are looking for a line that matches Mouse and then a string in parentheses. The contents of the parentheses are saved as $1 and are printed if the match was successful.

  2. grep + cut + tr

    $ bt-device --list grep Mouse | cut -d'(' -f2 | tr -d ')'
    34:88:5D:3F:1B:88
    

    Here, we use grep to find the relevant line(s), cut to print the second (-defined field (34:88:5D:3F:1B:88)) and tr to delete the trailing ).

  3. Just for fun, here's a solution with join:

    $ join -1 1 -2 2 -o 2.4 <(echo "Mouse (") <(bt-device --list) 2>/dev/null | tr -d '()'
    34:88:5D:3F:1B:88
    

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.