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
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.
Try this. It might not work depending on your grep version:
grep -m 1 -e pattern1 -e pattern2
You can use for each (see Linux Shell Script For Each File in a Directory Grab the filename and execute a program)
For each pattern you want to match execute a separate grep concatenating to the output file
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