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.

Input file1 is:

dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

I give the match the pattern from in other file ( like dog 123 4335 from file2).

I match the pattern of the line is dog 123 4335 and after printing all lines without match line my output is:

cat 13123 23424
deer 2131 213132
bear 2313 21313

If only use without address of line only use the pattern, for example 1s how to match and print the lines?

share|improve this question

10 Answers 10

$ more +/"dog 123 4335" file1

share|improve this answer
1  
It also works with less. –  brandizzi May 26 at 13:40
    
clever on the terminal, but it doesn't actually work if you pipe it into something else like tac. –  jcomeau_ictx Jul 2 at 6:25
    
i am using it like this , $ more +/"match my words" file1 >> file2 –  AMB 9 hours ago

Assuming you want to match the whole line with your pattern, with GNU sed, this works:

sed -n '/^dog 123 4335$/ { s///; :a; n; p; ba; }' infile

Standard equivalent:

sed -ne '/^dog 123 4335$/{s///; :a' -e 'n;p;ba' -e '}' infile

With the following input (infile):

cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

The output is:

cat 13123 23424 
deer 2131 213132
bear 2313 21313

Explanation:

  • /^dog 123 4335$/ searches for the desired pattern.
  • s/// empties pattern space, assuming you do not want the pattern included in the output.
  • :a; n; p; ba; is a loop that fetches a new line from input (n), prints it (p), and branches back to label a :a; ...; ba;.

Update

Here's an answer that comes closer to your needs, i.e. pattern in file2, grepping from file1:

tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1

The embedded grep and cut find the first line containing a pattern from file2, this line number plus one is passed on to tail, the plus one is there to skip the line with the pattern.

Note that not all versions of tail support the plus-notation.

share|improve this answer

If you have a reasonably short file grep alone might work:

grep -A5000 -m1 -e 'dog 123 4335' animals.txt

5000 is just my guess at "reasonably short", as grep finds the first match and outputs it together with the next 5000 lines (the file doesn't need to have that many). If you don't want the match itself you'll need to cut it off, e.g.

grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2


If you do not want the first, but the last match as delimiter you could use this:

tac animals.txt | sed -e '/dog 123 4335/q' | tac

This line reads animals.txt in reverse order of lines and outputs up to and including the line with dog 123 4335 and then reverses again to restore proper order.

Again, if you don't need the match in the result, append tail. (You could also complicate the sed expression to discard its buffer before quitting.)

share|improve this answer

One way using awk:

awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}'  file2 file1

where file2 contains your search patterns. First, all the contents of file2 are stored in the array "a". When the file1 is processed, every line is checked against the array, and printed only if is not present.

share|improve this answer
    
I think the OP wants to output every line following the pattern. –  Thor Nov 23 '12 at 11:41
    
@Thor : thanks for pointing it out, updated it now... –  Guru Nov 23 '12 at 11:57
    
Nicely done :). –  Thor Nov 23 '12 at 13:04
sed -e '1,/dog 123 4335/d' file1

If you need to read the pattern from a file, substitute it into the sed command. If the file contains a sed pattern:

sed -e "1,/$(cat file2)/d" file1

If the file contains a literal string to look for, quote all special characters. I assume the file contains a single line.

sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1

If you want the match to be the whole line, not just a substring, wrap the pattern in ^…$.

sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1
share|improve this answer
    
That won't work if the pattern is on the first line. GNU sed has 0,/dog.../d for that. –  Stéphane Chazelas Jun 10 at 9:48

My answer for the question in the subject, without storing pattern in a second file. Here is my test file:

$ cat animals.txt 
cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

GNU sed:

 $ sed '0,/^dog 123 4335$/d' animals.txt 
 cat 13123 23424 
 deer 2131 213132
 bear 2313 21313

Perl:

$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

Perl variant with pattern in a file:

$ cat pattern.txt 
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313
share|improve this answer

With awk:

awk 'BEGIN {getline pattern < "other file"}
   NR == 1, $0 ~ pattern {next}; {print}' < "input file"
share|improve this answer

If the input is an lseekable regular file:

With GNU grep:

{ grep  -xFm1 'dog 123 4335' >&2
  cat; } <infile 2>/dev/null >outfile

With sed:

{ sed -n '/^dog 123 4335$/q'
  cat; } <infile >outfile

A GNU grep called w/ the -m option will quit input at the match - and it will leave its (lseekable) input fd immediately after the point it found its last match. So calling grep w/ -m1 finds the first occurrence of a pattern in a file, and leaves the input offset at precisely the right place for cat to write everything following the pattern's first match in a file to stdout.

Even without a GNU grep you can do the exact same thing w/ a POSIX compatible sed - when sed quits it is specified to leave its input offset right where it does. GNU sed is not standards-compliant in this way, though, and so the above will likely not work w/ a GNU sed unless you call it with its -u switch.

share|improve this answer

In practice I'd probably use Aet3miirah's answer most of the time and alexey's answer is wonderful when wanting to navigate through the lines (also, it also works with less). OTOH, I really like another approach (which is kind of the reversed Gilles' answer:

sed -n '/dog 123 4335/,$p'

When called with the -n flag, sed does not print by default the lines it processes any more. Then we use a 2-address form that says to apply a command from the line matching /dog 123 4335/ until the end of the file (represented by $). The command in question is p, which prints the current line. So, this means "print all lines from the one matching /dog 123 4335/ until the end."

share|improve this answer
    
That prints the dog line though which is not wanted here. –  Stéphane Chazelas Jun 10 at 9:49

Since awk isn't expressly disallowed, here's my offering assuming 'cat' is the match.

awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i]  }' animals.txt
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.