I have a string of form FOO_123_BAR.bazquux
, where FOO
and BAR
are fixed strings, 123
is a number and bazquux
is freeform text.
I need to perform a text transformation on this string: extract 123
and bazquux
, increment the number and then arrange them in a different string.
For example, FOO_123_BAR.bazquux
⇒ FOO=124 BAR=bazquux
.
(Actual transformation is more complex.)
Naturally, I can do this in a sequence of sed and expr calls, but it's ugly:
shopt -s lastpipe
in=FOO_123_BAR.bazquux
echo "$in" | sed -r 's|^FOO_([0-9]+)_BAR\.(.+)$|\1 \2|' | read number text
out="FOO=$((number + 1)) BAR=$text"
Is there a more powerful text processing tool that can do the job in a single invocation? If yes, then how?
Edit: I apologize for not making this clearer, but the exact structure of the input and output is an example. Thus, I prefer general solutions that work with any delimiters or absence thereof, rather than solutions that depend on e. g. presence of underscores.
With GNU sed
, you can execute the entire replacement string as an external command using the e
flag.
$ s='FOO_123_BAR.bazquux'
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\2/e'
FOO=124 BAR=bazquux
To avoid conflict with shell metacharacters, you need to quote the unknown portions:
$ s='FOO_123_BAR.$x(1)'
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\2/e'
sh: 1: Syntax error: "(" unexpected
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\x27\2\x27/e'
FOO=124 BAR=$x(1)
Using any awk in any shell on every UNIX box and assuming none of your substrings contain _
or .
:
$ s='FOO_123_BAR.bazquux'
$ echo "$s" | awk -F'[_.]' '{print $1"="$2+1,$3"="$4}'
FOO=124 BAR=bazquux
You may do it with perl
:
perl -pe 's|^FOO_([0-9]+)_BAR\.(.+)$|"FOO=" . ($1 + 1) . " BAR=" . $2|e' <<< "$in"
See the online demo
The ($1 + 1)
will increment the number captured in Group 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With