From the first hi to the first hello that follows.
grep
Using (GNU) grep and tr:
$ <infile grep -oPz "(?s)hi.*?hello" | tr '\0' '\n'
hi aa bb cc
dd ee ff
hello
hi aaa bbb
ccc hello
Descripttion:
<infile
Source file.
grep -oPz
Call grep
to:
- (
-P
) match a PCRE (Perl Compatible Regular Expression)
- (
-o
) only print the matching part.
- (
-z
) use a zero byte (a.k.a. NUL and a.k.a. \0
) as line delimiter.
"(?s)
Make the PCRE dot (.
) match also newlines.
hi
Starting with the string hi
.
.*?
Match all characters that follow (non-greedy because of ?
).
hello"
Up until the string hello
is matched.
| tr '\0' '\n'
Convert the NULs (\0
) bytes (from grep -z
) to newlines.
sed
GNU sed:
<infile sed 's/hi/\n&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'
Or, for BSD sed, which doesn't allow \n
on the right side of s///
, you need to define a newline
variable nl
:
$ eval "$(printf "nl='\n'")"
And, then:
<infile sed 's/hi/\'"$nl"'&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'
Or; if you could write an explicit newline:
<infile sed 's/hi/\
&/;s/[^\n]*\n//;s/\(hello\).*/\1/;/hi/,/hello/!d'
hi
/hello
(on the same line and on consecutive lines) should be treated.