In bash, suppose that I have a string strname:


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:


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":


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


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

if [[ $strname =~ 3(.+)r ]]; then
    echo "unable to parse string $strname"

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.


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

case $strname in
    printf >&2 '%s\n' "Unable to parse string $strname"

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).

  • 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
    Commented 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. Commented 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 .