0

I have the following script to remove all lines before a line which matches with a word:

str='
1
2
3
banana
4
5
6
banana
8
9
10
'

echo "$str"  | awk -v pattern=banana '
  print_it {print} 
  $0 ~ pattern {print_it = 1}
'

It returns:

4
5
6
banana
8
9
10

But I want to include the first match too. This is the desired output:

banana
4
5
6
banana
8
9
10

How could I do this? Do you have any better idea with another command? I've also tried sed '0,/^banana$/d', but seems it only works with files, and I want to use it with a variable.

And how could I get all lines before a match using awk? I mean. With banana in the regex this would be the output:

1
2
3
mllamazares
  • 7,876
  • 17
  • 61
  • 89

4 Answers4

4

This awk should do:

echo "$str" | awk '/banana/ {f=1} f'
banana
4
5
6
banana
8
9
10
Jotne
  • 40,548
  • 12
  • 51
  • 55
3
sed -n '/^banana$/,$p'

Should do what you want. -n instructs sed to print nothing by default, and the p command specifies that all addressed lines should be printed. This will work on a stream, and is different than the awk solution since this requires the entire line to match 'banana' exactly whereas your awk solution merely requires 'banana' to be in the string, but I'm copying your sed example. Not sure what you mean by "use it with a variable". If you mean that you want the string 'banana' to be in a variable, you can easily do sed -n "/$variable/,\$p" (note the double quotes and the escaped $) or sed -n "/^$variable\$/,\$p" or sed -n "/^$variable"'$/,$p'. You can also echo "$str" | sed -n '/banana/,$p' just like you do with awk.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
2

Just invert the commands in the awk:

echo "$str"  | awk -v pattern=banana '
  $0 ~ pattern {print_it = 1}   <--- if line matches, activate the flag
  print_it {print}              <--- if the flag is active, print the line
'

The print_it flag is activated when pattern is found. From that moment on (inclusive that line), you print lines when the flag is ON. Previously the print was done before the checking.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Sorry, I clicked in other answer accidentally. :) – mllamazares Mar 21 '14 at 13:19
  • 1
    No, no problem at all :) I also think that other answer is shorter, but I just posted based on your original script. Also, note that `-v pattern="banana"` allows you to change the pattern or even give it from a bash variable with `-v pattern=$bash_var`. – fedorqui Mar 21 '14 at 13:20
  • And could you tell me how to get the lines after the match without including it? Thanks! :) – mllamazares Mar 24 '14 at 13:09
  • What do you mean? If it is the same question, edit it and show desired output. If it is something very different, it is better to ask a new question. – fedorqui Mar 24 '14 at 13:11
  • I've edited main post. Thanks for the advice, @fedorqui. – mllamazares Mar 24 '14 at 13:22
  • 1
    @JohnDoe you can use `echo "$str" | awk '/banana/ {exit} {print}'` – fedorqui Mar 24 '14 at 13:24
1
cat in.txt | awk "/banana/,0"

In case you don't want to preserve the matched line then you can use

cat in.txt | sed "0,/banana/d"
Joe Jobs
  • 201
  • 1
  • 12