Need grep for first occurrences of multiple lines

I am trying to return the first occurrence of multiple lines, i.e. I want to highlight lines from the following text where the first occurrence of 1259, 3009, and 1589 occurs.

ADWN 1259 11:00 B23 ADWN 3009 12:00 B19 DDWN 723 11:30 B04 ADWN 1589 14:20 B12 ADWN 1259 11:10 B23 DDWN 2534 13:00 B16 ADWN 3009 11:50 B14 

This gives me all the matches:

 grep '1259\|3009\|1589' somelog.log 

And that only gives me the first match

 grep -m 1 '1259\|3009\|1589' somelog.log 

I want to return the following:

 ADWN 1259 11:00 B23 ADWN 3009 12:00 B19 ADWN 1589 14:20 B12 

I think that creating a file with the required values ​​and then looping through the file, passing each number individually to the grep command will give me what I'm looking for, but I did not find an example of this. Is there a simple solution for this, is the loop the best way to handle this, or has this example already received an answer elsewhere?

Thanks in advance for your ideas and suggestions -

Clyde

+6
source share
4 answers

One way: awk :

 awk '!array[$2]++ && $2 ~ /^1259$|^3009$|^1589$/' file.txt 

Results:

 ADWN 1259 11:00 B23 ADWN 3009 12:00 B19 ADWN 1589 14:20 B12 

change

I should really get used to reading the whole question first. I see that you are thinking of creating a file with the values ​​that you would like to find in the first case. Place them in a file called values.txt with one value per line. For instance; here is the contents of values.txt :

 1259 3009 1589 

Then run this:

 awk 'FNR==NR { array[$0]++; next } $2 in array { print; delete array[$2] }' values.txt file.txt 

Results:

 ADWN 1259 11:00 B23 ADWN 3009 12:00 B19 ADWN 1589 14:20 B12 

Explanation of the first command:

If the second column ( $2 ) is equal to one of these three values, add it to the array if it does not already exist. awk prints the entire line by default.

Description of the second command:

FNR - the number of records relative to the current input file.
NR - total number of records.

The FNR==NR { ... } construct is valid only for the first input file. Therefore, for each of the lines in values.txt we add the entire line ( $0 ) to the array (I called it an array, but you could give it a different name). next causes awk to read the next line in values.txt (and skip processing the rest of the command). When FNR==NR ceases to be true, the second file in the argument list is read. Then we check the second column ( $2 ) in the array, if it is there, print it and remove it from the array. Using delete , we essentially set the maximum number of units.

+4
source

You can use for each (see Linux Shell Script for each file in the directory. Grab the file name and execute the program ) For each template that you want to map, run a separate grep concatenating with the output file

0
source

This one will work too.

 for i in $(cut -d " " -f1 somelog.log | sort -u); do LC_ALL=C fgrep -m1 "$i" somelog.log; done 
0
source

Try it. It may not work depending on your version of grep:

  grep -m 1 -e pattern1 -e pattern2 
-1
source

All Articles