4

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.

5 Answers 5

3

something like

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

should do the trick

2

You can use perl:

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

or using grep:

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

You can even use grep and sed as below.

grep -o 'SELECT.*$\|SSELECT.*$'  new.txt | sed 's/\[.*//'
1

Here is a pure POSIX grep solution:

grep -oE 'S?SELECT[^[]*' infile
0

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" 
2
  • This worked perfectly on the various *NIX variants I tested it. Thanks!
    – aaltonen
    Commented Mar 20, 2014 at 5:43
  • thanks, but did you checked also which strings are not matching?
    – user55518
    Commented Mar 20, 2014 at 12:04

You must log in to answer this question.

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