Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to grep for first occurrences of multiple strings

Tags:

grep

I am attempting to return the first occurrence of multiple strings, ie, I want to select the lines from the following text where the first occurrence of 1259, 3009, and 1589 happen.

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 matches:

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

And this gives me only 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 into the grep command will give me what I am looking for, but I haven't found an example of this. Is there a simple solution for this, is a loop the best way to handle this, or has this example already been answered elsewhere?

Thanks in advance for your ideas and suggestions--

Clyde

like image 950
comuter geek Avatar asked Nov 03 '12 00:11

comuter geek


People also ask

How do you grep the first occurrence?

Using head To Limit grep Output It's still a little useful to use -m 1 with grep though, as it will stop processing large files if a match is found early. This works with the -o flag to print only the first match, even if there are multiple matches in a file: However, be careful when using this with multiple files.

How do we use grep to search for a pattern in multiple files?

To search multiple files with the grep command, insert the filenames you want to search, separated with a space character. The terminal prints the name of every file that contains the matching lines, and the actual lines that include the required string of characters. You can append as many filenames as needed.

How do you grep with additional lines?

To also show you the lines before your matches, you can add -B to your grep. The -B 4 tells grep to also show the 4 lines before the match. Alternatively, to show the log lines that match after the keyword, use the -A parameter. In this example, it will tell grep to also show the 2 lines after the match.


1 Answers

One way using 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

edit:

I should really get into the habit of reading the whole question first. I see that you're thinking of creating a file with the values you'd like to find the first occurrence of. Put these in a file called values.txt with one value per line. For example; here's 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

1st command explanation:

If the second column ($2) equals one of those three values listed, add it to the array if it's not already in there. awk prints the whole line by default.

2nd command explanation:

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

The FNR==NR { ... } construct is only true for the first input file. So for each of the lines in values.txt, we add the whole line ($0) to an array (I've called it array, but you could give it another name). next forces awk to read the next line in values.txt (and skip processing the rest of the command). When FNR==NR is no longer true, the second file in the arguments list is read. We then check for the second column ($2)in the array, if it's in there, print it and remove it from the array. By using delete we essentially set a max count of one.

like image 179
Steve Avatar answered Sep 20 '22 15:09

Steve