0

I'm trying to create a script that automatically looks for plugged in devices and makes a compressed backup of it. However, I'm having trouble finding the correct way on how to use expr:

#!/bin/bash

MountText=`mount`
# Show result of regex search
expr "$MountText" : '\/dev\/(sd[^a])\d on [\S]+\/[\s\S]+? type'

The expression by itself is \/dev\/(sd[^a])\d on [\S]+\/[\s\S]+? type, and captures the device name (sd*), while excluding mounts relating to sda.

I drafted the regex on Regexr (regex shared in link), and used what mount dumped (gist).

For some reason, it only gives this odd error:

0

I looked around, and I found this SO question. It didn't help me too much, because now it's implying that expr didn't recognize the parentheses I used to capture the device, and it also believed that the expression didn't capture anything!

I'm really confused. What am I doing wrong?

8
  • 1
    Regular expressions only work within languages, shells use wildcards or globs, please google these terms for the shell you are using, **echo $SHELL ** Commented Mar 2, 2016 at 0:59
  • Thanks, didn't hear any information that expr uses globs. Though, I don't get what you mean by echo $SHELL, because I mentioned both in tags and in the hashbang that I'm using bash. Commented Mar 2, 2016 at 1:05
  • @ArifBurhan Also, I checked the man pages, and it says that the phrase expr STRING : REGEXP uses regular expressions. Commented Mar 2, 2016 at 1:14
  • echo $(...) is almost always redundant; there's no reason to capture the output of a command just to output it. Commented Mar 2, 2016 at 2:19
  • @chepner I commented that I wanted to see what It would produce. If I immediately put it into a script, it might have dangerous consequences. Commented Mar 2, 2016 at 2:22

1 Answer 1

1

A few things to note with expr:

  1. The regular expression is implicitly anchored at the beginning of the string (as if you started the expression with ^).
  2. The capture group is indicated with escaped parentheses, \(...\).
  3. Only basic regular expressions are supported. Specifically, \s, \S, and +? are not supported.

The following will match the one device.

expr "$MountText" : '.*/dev/\(sd[^a]\)[[:digit:]] on '

Note that you don't need to use expr with bash, which has regular-expression matching built in.

regex='/dev/(sd[^a])[[:digit:]] on '
mount | while IFS= read -r line; do
    [[ $line =~ $regex ]] && echo ${BASH_REMATCH[1]}
done
Sign up to request clarification or add additional context in comments.

3 Comments

This gives the same error as before, so while some of this might help me, it still doesn't work. Did you test it out with the gist I had?
Sorry, tried to do too much from memory. Updating, but there is one caveat: you can only capture the first device that matches, not any more. (The non-greedy +? operator isn't supported, but would be unnecessary anyway.)
This works! I don't believe I will need to find other devices, but if I need to, I think I can use string manipulation to remove the captured line. Thanks so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.