0
votes

I have one of the 2 possible texts:

 myProg vFOO 3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)
 myProg v3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)

How can I ignore the whole "FOO" string in my sed regex? So it'll print:

 v3.1.2.11.1+build4

I was using:

 sed -n '/myProg v/s/.*myProg v["FOO "]\([[:alnum:][:punct:]]*\).*/v\1/gp'

Thanks

3
Is there a reason you want to use sed? Would a native-bash implementation that required no sed at all be acceptable?Charles Duffy
I think I previously wrote this code to support old AIX servers we had. Couldn't install newer bash nor use the grep -Po. sed was the better option I found.Maxim_united
I also preferred to do it in a single line as pipe manipulationMaxim_united
"In a single line" is easy enough using =~ -- I did two operations just out of laziness (to unify the cases before invoking the regex, and thus reduce the complexity / testing requirements for same). "As pipe manipulation" -- well, if that fits for what you're doing; just be aware that it has a performance cost.Charles Duffy

3 Answers

4
votes

You don't need sed for this at all -- and when operating only on a single line, using bash builtins only is far faster than running an external program and reading its output.

s='myProg vFOO 3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)'
[[ $s = *" vFOO "* ]] && s=${s//vFOO /v}
[[ $s =~ (v[[:alnum:]][^[:space:]]+) ]] && echo "${BASH_REMATCH[1]}"

...emits...

v3.1.2.11.1+build4
4
votes

You are making the extremely common mistake of using square brackets for grouping. That's not what they do; they create a character class. You are looking for regular round parentheses (which apparently need to be backslash-quoted in your dialect of sed):

sed -n 's/.*myProg v\(FOO \)\?\([[:alnum:][:punct:]]*\).*/v\2/p'

The initial /myProg v/ which you had, while well-intentioned, didn't really serve a useful purpose; the above script will only print lines where the substitution is successful, anyway.

(The /g flag you had were simply not useful, as there would only ever be a single match on a line of input.)

This is assuming your sed accepts \? to mean "zero or one repetition". If it doesn't, you can somewhat inexactly but safely trade a * wildcard instead.

1
votes

how about grep:

grep -Po 'myProg v\D*\K[\d.]*'

with build... info:

grep -Po 'myProg v\D*\K\S*' 

with your text:

kent$ echo "myProg vFOO 3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)
 myProg v3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)"|grep -Po 'myProg v\D*\K[\d.]*'
3.1.2.11.1
3.1.2.11.1

kent$ echo "myProg vFOO 3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)
 myProg v3.1.2.11.1+build4 (Build time: Aug  7 2014 15:33:58)"|grep -Po 'myProg v\D*\K\S*'   
3.1.2.11.1+build4
3.1.2.11.1+build4