Regarding grep command
I have two queries开发者_开发问答
I do a grep and get the line number of the input file. i want to retrieve a set of lines before and after the line number from the inputfile and redirect to a /tmp/testout file. how can i do it.
I have a line numbers 10000,20000. I want to retrieve the lines between 10000 and 20000 of the input file and redirect to a /tmp/testout file. how can i doi it
for grep -C is the straight forward option
for the 2nd question try this!
sed -n "100000,20000p" bar.txt > foo.txt
You want to look into the -A -B and -C options of grep. See man grep
for more information
-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines.
Places a line containing -- between contiguous groups of
matches.
-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines.
Places a line containing -- between contiguous groups of
matches.
-C NUM, --context=NUM
Print NUM lines of output context. Places a line containing --
between contiguous groups of matches.
For redirecting the output, do the following: grep "your pattern" yourinputfile > /tmp/testout
See head
and/or tail
.
For example:
head -n 20000 <input> | tail -n 10000 > /tmp/testout
whereas the argument of tail is (20000 - 10000).
If you're using GNU grep, you can supply -B
and -A
to get lines before and after the match with grep.
E.g.
grep -B 5 -A 10 SearchString File
will give print each line matching SearchString from File plus 5 lines before and 10 lines after the matching line.
For the other part of your question, you can use head/tail or sed. Please see other answers for details.
For part 2, awk
will allow you to print a range of lines thus:
awk 'NR==10000,NR==20000{print}{}' inputfile.txt >/tmp/testout
This basically gives a range based on the record number NR
.
For part 1, context from grep
can be obtained using the --after-context=X
and --before-context=X
switches. If you're running a grep
that doesn't allow that, you can dummy up an awk
script based on the part 2 answer above.
to see the before and after: (3 lines before and 3 lines after)
grep -C3 foo bar.txt
the second question:
head -20000 bar.txt | tail -10000 > foo.txt
you can do these with just awk, eg display 2 lines before and after "6", and display range from linenumber 4 to 8
$ cat file
1
2
3
4
5
6
7
8
9
10
$ awk 'c--&&c>=0{print "2 numbers below 6: "$0};/6/{c=2;for(i=d;i>d-2;i--)print "2 numbers above 6: "a[i];delete a}{a[++d]=$0} NR>3&&NR<9{print "With range: ->"$0}' file
With range: ->4
With range: ->5
2 numbers above 6: 5
2 numbers above 6: 4
With range: ->6
2 numbers below 6: 7
With range: ->7
2 numbers below 6: 8
With range: ->8
If your grep
doesn't have -A
, -B
and -C
, then this sed
command may work for you:
sed -n '1bb;:a;/PATTERN/{h;n;p;H;g;bb};N;//p;:b;99,$D;ba' inputfile > outputfile
where PATTERN
is the regular expression your looking for and 99
is one greater than the number of context lines you want (equivalent to -C 98
).
It works by keeping a window of lines in memory and when the regex matches, the captured lines are output.
If your sed
doesn't like semicolons and prefers -e
, this version may work for you:
sed -n -e '1bb' -e ':a' -e '/PATTERN/{h' -e 'n' -e 'p' -e 'H' -e 'g' -e 'bb}' -e 'N' -e '//p' -e ':b' -e '99,$D' -e 'ba' inputfile > outputfile
For your line range output, this will work and will finish a little more quickly if there are a large number of lines after the end of the range:
sed -n '100000,20000p;q' inputfile > outputfile
or
sed -n -e '100000,20000p' -e 'q' inputfile > outputfile
精彩评论