Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

What's the best way to print the text between (and including) the first pattern ("SELECT" or "SSELECT") and a second pattern ("[") using a command-line took (e.g. cut, sed, awk)?

For example, given the following:

 54001744  KB035928      20  /dev/pts/8      SELECT PRINTER.LOCS WITH SHIP.TICK.BR = "15" [ INP @ 0x67E ]
 26083642  RV091101      25  /dev/pts/14     SSELECT PRODUCT BY STK.LN.SEQ [ MENU.SELECT @ 0x10C ]
 57082018  hajohug     0xACEBF1C1  SELECT ORDER.QUEUE WITH &INDEX&.STATUS = "S~S]" "H~S]" "A~S]" "M~S]" AND WITH &INDEX&.SBR "51 17~]" [ SOE.PH.ORDER.PRINT @ 0x384 ]
 50266386  hajohug     0xACEBF2F0  SSELECT UD.VIEWS WITH &INDEX& = "ORDERENTRY.ORDERENTRY~0" [ SOCKET.READ @ 0x168 ]

The result should be:

SELECT PRINTER.LOCS WITH SHIP.TICK.BR = "15"
SSELECT PRODUCT BY STK.LN.SEQ
SELECT ORDER.QUEUE WITH &INDEX&.STATUS = "S~S]" "H~S]" "A~S]" "M~S]" AND WITH &INDEX&.SBR "51 17~]"
SSELECT UD.VIEWS WITH &INDEX& = "ORDERENTRY.ORDERENTRY~0"

I've tried using cut, but I haven't been able to get things looking right.

share|improve this question

5 Answers 5

up vote 0 down vote accepted

To exactly match the final sequence in square brackets:

perl -alne 'm/S?SELECT.*?(?=\[ \S+ @ \S+ \]$)/ && print $&;' file

outputs

SELECT PRINTER.LOCS WITH SHIP.TICK.BR = "15" 
SSELECT PRODUCT BY STK.LN.SEQ 
SELECT ORDER.QUEUE WITH &INDEX&.STATUS = "S~S]" "H~S]" "A~S]" "M~S]" AND WITH &INDEX&.SBR "51 17~]" 
SSELECT UD.VIEWS WITH &INDEX& = "ORDERENTRY.ORDERENTRY~0" 
share|improve this answer
    
This worked perfectly on the various *NIX variants I tested it. Thanks! –  aaltonen Mar 20 at 5:43
    
thanks, but did you checked also which strings are not matching? –  user55518 Mar 20 at 12:04

You can use perl:

perl -nle 'print $1 if /(S?SELECT.*?)\[/' file

or using grep:

grep -Po 'S?SELECT.*?(?=\[)' file
share|improve this answer
    
S?SELECT or S{1,2}ELECT would be meet the requirements more exactly. You'll probably want .*? to be non-greedy before the [ –  glenn jackman Mar 19 at 15:12
    
Why do we need non-greedy? –  Gnouc Mar 19 at 15:16
    
In case there are more than 1 [ on a line. –  glenn jackman Mar 19 at 15:18
    
because there are ] in the strings, the strings could also contain a [ –  user55518 Mar 19 at 15:18
    
Yeap, I only try on OP's input. Fixed! –  Gnouc Mar 19 at 15:23

something like

sed 's@.*\(S*SELECT[^[]*\).*@\1@' foo

should do the trick

share|improve this answer

You can even use grep and sed as below.

grep -o 'SELECT.*$\|SSELECT.*$'  new.txt | sed 's/\[.*//'
share|improve this answer

Here is a pure POSIX grep solution:

grep -oE 'S?SELECT[^[]*' infile
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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