Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed - Get only the replaced string from a multiline input & omit unmatched lines!

Tags:

I want sed to omit all non-matching lines, and only output the replaced string (of the single/multiple intended line/s).

In other words: I've got a hay stack, and only want the needle returned, not all the hay which was searched and which remained unaltered.

Or again in other words: Search/replace a RegEx described string in a multi line string, and only get that string returned. (As it is possible with the PHP function http://www.php.net/manual/en/function.preg-replace.php )

My current workaround is to first filter with grep, and then pipe only the matching lines into sed for replacement:

echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | egrep "^Important1.*$" | sed -E "s/^Important1: *\b(.*)\b */\1/g"
# From the multiple line input I only want the "One One" (with pre/post whitespace removed, hence matching the word boundaries with "\b")
# And I want no "Bla bla" lines in the result!

But I'd like to have a single solution within sed. Or is this out of intended sed usage, and should I therefore better use something else? Btw, issue: multiline sed using backreferences seemed somehow related, but I am not sure!

like image 850
porg Avatar asked Apr 04 '11 21:04

porg


People also ask

Does sed work on multiple lines?

By using N and D commands, sed can apply regular expressions on multiple lines (that is, multiple lines are stored in the pattern space, and the regular expression works on it): $ cat two-cities-dup2.

How do you use sed on a specific line?

Just add the line number before: sed '<line number>s/<search pattern>/<replacement string>/ . Note I use . bak after the -i flag. This will perform the change in file itself but also will create a file.


2 Answers

EDIT: Following was tested on both Mac & Linux.

You can use sed like this:

echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | \
   sed -n 's/^Important1: *\([^ ]*\) */\1/p'

OUTPUT:
one

Explanation

sed -n 's/^Important1: *\([^ ]*\) */\1/p'

-n # quiet / silent 

{
  s/^Important1: *\([^\ ]*\) */\1/ # replace "Important1: one " with 1st group i.e. "one"
  p                  # print the replaced text
}
like image 160
anubhava Avatar answered Sep 28 '22 10:09

anubhava


This sed command does what your combination of egrep and sed does:

echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla"
| sed -n -e "s/^Important1: *\b\(.*\)\b */\1/p"

You perform the substitution and only print lines that matched, after the substitution.

like image 37
Christian Semrau Avatar answered Sep 28 '22 09:09

Christian Semrau