0

I've got a series of patterns stored in foo.txt and I want to iterate over those patterns and see which match lines in file bar.txt.

while read PWW
do
   cat user/dump/bar.txt | awk '/${PWW}/{print $2}' >> user/dump/out.txt
done < user/dump/foo.txt

foo.txt:

2100001b32
2100001b38
3100001b35
4100001b28
5100001b46
6100001b56

bar.txt:

2100001b32 good
2100001b38 bad
3100001b35 okay
4100001b28 large
5100001b46 good
6100001b56 bad

desired out.txt:

good
bad
okay
large
good
bad

I am unable to search for the values in foo.txt. The while loop runs and gives me empty output. I guess awk is looking for ${PWW} (literally) instead of its values from foo.txt.

How can I make it work? My environment is Solaris 5.10, using Korn shell, with basic awk (old awk).

4
  • 2
    Don't use your approach! (Remove useless cats, avoid loops in shells if possible, don't repeatedly call (awk-) processes in loops unnecessarily.) - Instead use an awk-only approach, like the suggested "pure awk" answer below. - awk can accept a file list (as many other commands also do), it does implicit (fast) looping, and the resulting code is much simpler. Commented May 28, 2015 at 19:13
  • @Janis my question is just an example. In reality what i wanted can only be achieved with loop. if its just a single file operation i could have done a straight-forward AWK. Thanks for your suggestion. Commented May 28, 2015 at 19:20
  • 1
    awk accepts lists of files as arguments, not only "single file". - As said; the way you wrote your sample (with all its deficiencies) is a strong indication that you may not know what's possible or sensible. - It would be helpful if you just tell us exactly "what you wanted"; we could certainly make good suggestions. - Anyway; your choice. Commented May 28, 2015 at 20:00
  • The problem as stated could probably be done with a grep -f foo.txt. If there are additional constraints, edit the question accordingly. Commented May 30, 2015 at 8:29

3 Answers 3

5

Here is a pure-awk solution:

$ awk 'FNR==NR{a[$1]=$2; next} {print a[$1]}' bar.txt foo.txt
good
bad
okay
large
good
bad

How it works

The script reads in bar.txt first and saves its information in array a. It then reads foo.txt and prints out the corresponding value.

  • FNR==NR{a[$1]=$2; next}

    FNR is the number of lines read from the current file and NR is the number of lines read so far total. Thus, if FNR==NR, we are still reading the first file (bar.txt). If so, a[$1]=$2 is used to add an entry to array a saving these values. Then, we skip the rest of the commands in the script and start over on the next line.

  • print a[$1]

    If we get here, we are reading the second file, foo.txt. We read foo.txt line by line. For each line, we look up the value corresponding to the key in the first column and print it.

1

Check your quotes. In unix shells including bash: single quotes pass text unmodified to the program (so as you said passes ${PWW}, double quotes allow expansion of variables.

In your example you want ${PWW} to be expanded but not $2, you can do this like this:

awk "/${PWW}/"'{print $2}'
awk /${PWW}/{print '$2'}
awk "/${PWW}/{print \$2}"
1
  • Thank you so much, i did not know the difference between double quote and single quote. Now i will remember. Its working now. Commented May 28, 2015 at 17:25
1

The canonical method of passing string values from the shell into awk is through the -v var=val option.

If you want to use those strings for a pattern match, traditionally with /.../, you need write an explicit match against the entire line:

awk -v pattern=${PWW} '$0 ~ pattern {print $2}'

BTW, for Solaris 10, nawk is recommended over plain old awk, if only for better error messages than "bailing out at ..."

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.