4

It's a bit of a contrived example but here goes: Say I have a variable 1.2.3.4 containing version information and need to replace the .4 at the end with .5

version=1.2.3.4
echo ${version%.*}.5
1.2.3.5    #no problem

But when I attempt to "in-line" the substitution with / and a % anchor

echo ${version/%.*/.5}
1.5

Bash does a greedy substitution. Is there a way to have bash take the substitution up "non-greedily" so I can use substitution as a replacement for the earlier delete+append approach?

4

Not in general but easily in this case:

shopt -s extglob
echo ${version/%+([0-9])/}
1.2.3.
  • Dankeschön, works in the simple case. I am going to have to learn to live without it for the more complex cases – iruvar Mar 1 '14 at 4:47
4

I think you can not non-greedy in search and replace, you can only do it with substring removal. From bash references:

${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with ‘#’, it must match at the beginning of the expanded value of parameter. If pattern begins with ‘%’, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / following pattern may be omitted. If parameter is ‘@’ or ‘’, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with ‘@’ or ‘’, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.

To solved this, you should set extglob:

shopt -s extglob
printf '%s\n' "${version/%.+([0-9])/.5}"
1.2.3.5

or use some tools like sed or perl:

printf '%s\n' "$version" | perl -pe 's/\.\d+$/\.5/'
1.2.3.5
  • gnouc, much appreciate the detailed response and +1. Accepted Hauke's on a first-past-the-post basis – iruvar Mar 1 '14 at 4:45

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.