28

I want to start grepping from the lines that has CK at the end of line and stop grepping when the line has D at the end. I tried grep "$CK" "$D" file..txt, but it didn't work.

Input:

kkkkkkkkkkk   
jjjjjjjjjjjjjjjjjj  
gggggggggggg/CK  
JHGHHHHHHHH   
HJKHKKLKLLL   
JNBHBHJKJJLKKL  
JLKKKLLKJLKJ/D  
GGGGGGGGGGGGGG  
GGGGGGGGGGGGGG

The desired output:

gggggggggggg/CK  
JHGHHHHHHHH   
HJKHKKLKLLL   
JNBHBHJKJJLKKL  
JLKKKLLKJLKJ/D

4 Answers 4

33

You are better off using or

awk '/CK$/,/D$/' file.txt

OR

sed -n '/CK$/,/D$/p' file.txt

If you insist on , here's a GNU grep way

grep -oPz '(?s)(?<=\n)\N+CK\n.*?D(?=\n)' file.txt

Here

-P activates perl-regexp

-z sets line separator to NUL. This forces grep to see the entire file as one single line

-o prints only matching

(?s) activates PCRE_DOTALL, so . finds any character or newline

\N matches anything except newline

.*? finds . in nongreedy mode

(?<=..) is a look-behind assertion

(?=..) is a look-ahead assertion

10
  • why not added slash ? like this awk '/\/CK/,/\/D/' input Nov 8, 2013 at 17:37
  • @RahulPatil, that's because the OP stated 'start grepping from the lines that has "CK" at the end of line and stop grepping when the line has "D"'
    – iruvar
    Nov 8, 2013 at 17:38
  • it seems me, you have strong understanding of regex.. I didn't understand that level, so could you please explain that last of PCRE grep Nov 8, 2013 at 17:41
  • @RahulPatil, added some explanation :-)
    – iruvar
    Nov 8, 2013 at 18:14
  • @RohitPatil, I want to delete the matching selection from the file. can i do that?
    – Rana Khan
    Nov 8, 2013 at 18:18
0

If you're using BSD grep (doesn't support perl regex param -P), here is the workaround:

grep -o "aaa.*cdn" <(paste -sd_ file) | tr '_' '\n'

This works by concatenating all lines (replacing new lines with _ character), checking the one-line pattern and expanding the lines back to its original state.

If you're using GNU grep, you can achieve multiline match in grep, but you need to use perl-regexp for grep (-P) like mentioned in another answer. You can still install GNU grep on macOS via brew install grep and use ggrep instead.


Alternatively you can use pcregrep which supports multi-line patterns (-M).


You can also use ex command, e.g.:

ex +"/aaa/;/cdn/p" -scq! file
0
`awk '/CK$/{f=1}/D$/{f=0;print;exit}f' filename

gggggggggggg/CK
JHGHHHHHHHH
HJKHKKLKLLL
JNBHBHJKJJLKKL
JLKKKLLKJLKJ/D
0

Using Perl(5):

perl -nE 'print $_ if /CK$/.../D$/;'

Using Raku (formerly known as Perl_6):

raku -ne 'put $_ if /CK$/fff/D$/;'

Both lines of code above use a sed-like "flip-flop" operator. In Perl5 the sed-like "flip-flop" is spelled .... In Raku the sed-like "flip-flop" is spelled fff.

Sample Input:

kkkkkkkkkkk   
jjjjjjjjjjjjjjjjjj  
gggggggggggg/CK  
JHGHHHHHHHH   
HJKHKKLKLLL   
JNBHBHJKJJLKKL  
JLKKKLLKJLKJ/D  
GGGGGGGGGGGGGG  
GGGGGGGGGGGGGG

Sample Output (either Perl5 or Raku):

gggggggggggg/CK
JHGHHHHHHHH
HJKHKKLKLLL
JNBHBHJKJJLKKL
JLKKKLLKJLKJ/D

Note, because Raku uses the . dot to chain operations, the Raku code starting put $_ … can be written $_.put … . Also, if a method chain starts with a . dot, Raku defaults to calling the chain on the $_ topic variable. Thus the Raku code presented above can be shortened to $_.put … and even further shortened to .put … .

https://perldoc.perl.org/perlop
https://raku.org

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .