18

In bash, suppose that I have a string strname:

strname="ph7go04325r"

I would like to extract the characters between the first "3" character and the last "r" character in strname, saving the result in a string strresult. In the example above, the resulting strresult would be:

strresult="25"

The first "3" character is not necessarily at string position 8 in strname; likewise, the last "r" is not necessarily at string position 11. Thus, both of the following strings strname should yield strresult="25":

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

Also, strname=ph12go04330raa" should yield strresult="30".

I am new to bash scripting, and I don't know where to begin to do string pattern matching like this. Do you have any suggestions?

2 Answers 2

34

You can use a regex in bash (3.0 or above) to accomplish this:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

In bash, capture groups from a regex are placed in the special array BASH_REMATCH. Element 0 contains the entire match, and 1 contains the the match for the first capture group.

10

In standard sh syntax (so would work with any version of bash or any other POSIX compliant shell), you would do:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

See also the old expr solution which will even work on 35 year old Unices:

expr "x$strname" : 'x[^3]*3\(.*\)r'

The old quirk with expr is that if the match fails you get a non-zero exit status (fine), but you also get a non-zero exit status if the returned strings resolves to 0 (like with strname=zz300rzz).

2
  • I think your phrasing incorrectly implies that this can only be done with older versions of bash. The parameter expansion is, of course, still a fine approach in modern shells.
    – kojiro
    Feb 4, 2013 at 20:55
  • 1
    @kojiro, I see what you mean. The initial formulation was to follow-up on Jordan's answer. I've updated my answer. Feb 4, 2013 at 21:02

You must log in to answer this question.

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