How to save matched pattern into variable using 'sed' command?
Solution 1
Here is a single invocation of sed that writes the revised line to stdout while at the same time saving the removed text in shell variable var
:
$ var=$(echo "This X is test Y. But X is not test Y." | sed -nr 'h;s/[^X]*X([^Y]*)Y.*/\1/;p;x;s/X[^Y]*Y/REPLACE/;w /dev/stderr') 2>&1
This REPLACE. But X is not test Y.
The value of var
is:
$ echo "==$var=="
== is test ==
Explanation:
h
This command copies the current pattern to the hold space.
s/[^X]*X([^Y]*)Y.*/\1/;p
This removes everything from the pattern space except the text between the first
X
andY
including any spaces. This is then printed to stdout. This is the output that is captured by the shell and assigned tovar
.x
This copies the hold space back to the pattern space. When this is done, the pattern space contains a copy of the original input line.
s/X[^Y]*Y/REPLACE/; w /dev/stderr
The substitution is made and the result is written to
stderr
.2>&1
After the shell has captured stdout into
var
, this instructs the shell to copy stderr (which has the line with REPLACE) to stdout.
Aside on handling of variable var
The variable var
includes the leading and trailing spaces. If the shell were to subsequently subject var
to word-splitting, these spaces would be removed. To prevent that, when var
is referenced, do so inside double-quotes, as in the example above.
Solution 2
You have to accomplish that with a second sed command:
var=$(echo "This X is test Y. But X is not test Y." | \
tee >(sed 's/X[^Y]*Y/REPLACE/' >/dev/stderr) | \
sed -r 's/[^X]*X([^Y]*)Y.*/\1/')
Exlanation:
- You have to use
tee
to split the stream. That bothstdout
andstderr
contain the string. tee
needs a file as argument. We givetee
a pipe wheresed
listens from and replaces the string.sed
prints the string tostderr
: The output you see in the terminal.- The second
sed
command listens onstdout
and extracts the needed string, that is now saved into the variable$var
(the contect ofstdout
).
Use that to check:
$ echo ">$var<"
> is test <
Related videos on Youtube
αғsнιη
SeniorDevOpsEngineer at #HUAWEI since March-2015 (#opentowork https://www.linkedin.com/in/-rw-r--r--) ʷⁱˡˡⁱⁿᵍ ᵗᵒ ˢᵉᵉ ʸᵒᵘ ⁱⁿ ᵃ ᵐⁱʳʳᵒʳ ᵐᵃᵈᵉ ᵒᶠ ᵐʸ ᵉʸᵉˢ # touch 'you ◔◡◔'
Updated on September 18, 2022Comments
-
αғsнιη over 1 year
I'm trying to find a pattern using
sed
command infile.txt
between first char1 and char2 and then replace that with string. like below withecho
mode example:echo "This X is test Y. But X is not test Y." | sed 's/X[^Y]*Y/REPLACE/'
Also I need to save matched pattern( like
is test
{<--spaces around is important} ) in a variable.-
muru over 9 yearsIn a shell variable? Because you can use backreferences in sed: sed
's/X\([^Y]*\)Y/\1/'
- the\1
will contain everything matched by[^Y]*
. -
αғsнιη over 9 years@muru I've also tried that, correct, but I need to replace that with new word and save into a variable like "VAR"
-