24

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

29

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.