开发者

How to ignore all lines before a match occurs in bash?

I would lik开发者_Python百科e ignore all lines which occur before a match in bash (also ignoring the matched line. Example of input could be

R1-01.sql
R1-02.sql
R1-03.sql
R1-04.sql
R2-01.sql 
R2-02.sql
R2-03.sql

and if I match R2-01.sql in this already sorted input I would like to get

R2-02.sql
R2-03.sql


Many ways possible. For example: assuming that your input is in list.txt

PATTERN="R2-01.sql"
sed "0,/$PATTERN/d" <list.txt

because, the 0,/pattern/ works only on GNU sed, (e.g. doesn't works on OS X), here is an tampered solution. ;)

PATTERN="R2-01.sql"
(echo "dummy-line-to-the-start" ; cat - ) < list.txt | sed "1,/$PATTERN/d"

This will add one dummy line to the start, so the real pattern must be on line the 1 or higher, so the 1,/pattern/ will works - deleting everything from the line 1 (dummy one) up to the pattern.

Or you can print lines after the pattern and delete the 1st, like:

sed -n '/pattern/,$p' < list.txt | sed '1d'

with awk, e.g.:

awk '/pattern/,0{if (!/pattern/)print}' < list.txt

or, my favorite use the next perl command:

perl -ne 'print unless 1../pattern/' < list.txt

deletes the 1.st line when the pattern is on 1st line...

another solution is reverse-delete-reverse

tail -r < list.txt | sed '/pattern/,$d' | tail -r

if you have the tac command use it instead of tail -r The interesant thing is than the /pattern/,$d' works on the last line but the1,/pattern/d` doesn't on the first.


How to ignore all lines before a match occurs in bash?

The question headline and your example don't quite match up.

Print all lines from "R2-01.sql" in sed:

sed -n '/R2-01.sql/,$p' input_file.txt

Where:

  • -n suppresses printing the pattern space to stdout
  • / starts and ends the pattern to match (regular expression)
  • , separates the start of the range from the end
  • $ addresses the last line in the input
  • p echoes the pattern space in that range to stdout
  • input_file.txt is the input file

Print all lines after "R2-01.sql" in sed:

sed '1,/R2-01.sql/d' input_file.txt
  • 1 addresses the first line of the input
  • , separates the start of the range from the end
  • / starts and ends the pattern to match (regular expression)
  • $ addresses the last line in the input
  • d deletes the pattern space in that range
  • input_file.txt is the input file
  • Everything not deleted is echoed to stdout.


This is a little hacky, but it's easy to remember for quickly getting the output you need:

$ grep -A99999 $match $file

Obviously you need to pick a value for -A that's large enough to match all contents; if you use a too-small value the output will be silently truncated.

To ensure you get all output you can do:

$ grep -A$(wc -l $file) $match $file

Of course at that point you might be better off with the sed solutions, since they don't require two reads of the file.

And if you don't want the matching line itself, you can simply pipe this command into tail -n+1 to skip the first line of output.


awk -v pattern=R2-01.sql '
  print_it {print} 
  $0 ~ pattern {print_it = 1}
'


you can do with this,but i think jomo666's answer was better.

sed -nr '/R2-01.sql/,${/R2-01/d;p}' <<END
    R1-01.sql
    R1-02.sql
    R1-03.sql
    R1-04.sql
    R2-01.sql
    R2-02.sql
    R2-03.sql
    END


Perl is another option:

perl -ne 'if ($f){print} elsif (/R2-01\.sql/){$f++}' sql

To pass in the regex as an argument, use -s to enable a simple argument parser

perl -sne 'if ($f){print} elsif (/$r/){$f++}' -- -r=R2-01\\.sql file


This can be accomplished with grep, by printing a large enough context following the $match. This example will output the first matching line followed by 999,999 lines of "context".

grep -A999999 $match $file

For added safety (in case the $match begins with a hyphen, say) you should use -e to force $match to be used as an expression.

grep -A999999 -e '$match' $file
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜