LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Awk Related Question (https://www.linuxquestions.org/questions/linux-newbie-8/awk-related-question-799383/)

dragonandante 04-01-2010 09:53 AM

Awk Related Question
 
I'm trying to get the following script to work.

Quote:

while read line
do

awk '
/$line/ {
print $2
print $3
print "\r"
}
' changes.txt > email.txt

# Add in a email line later

done < "usernames.txt"
However this doesn't work. Also, I'm trying to get it to print the very next line as well.

Here are examples of changes.txt and username.txt

Quote:

username.txt

username1
username2
username3
Quote:

changes.txt

username1 somedate /somedirectory
Comment: I enjoy some moist cake
username2 somedate /somedirectory
Comment: Pie is better
username3 somedate /somedirectory
Comment: No love for cookies?
username1 somedate /somedirectory
Comment: Hell no, cake all the way
So each user would get an email detailing only what they did.
For example usernam1 would get an email with the following in the body:

Quote:

username1 somedate /somedirectory
Comment: I enjoy some moist cake

username1 somedate /somedirectory
Comment: Hell no, cake all the way
So to sum it up, I'm trying to get awk to cycle through the usernames list, and to print the very next line as well. Any help or hints will be greatly appreciated.

David the H. 04-01-2010 12:44 PM

Code:

while read line; do

  awk '/$line/ {print $2print $3print "\r"}' changes.txt > email.txt
  # Add in a email line later

done < "usernames.txt"

(condensed for space and readability)

Well, first of all there's your variable. A bash variable can't expand when enclosed inside single quotes.

To use a bash variable in awk, you either have to quote it carefully, or import it into an awk variable, as explained here.

http://www.grymoire.com/Unix/Awk.html#uh-4

In addition, you generally only use a single print command per line, and you can't just use a carriage return to get the next line. awk has a special "getline" function for that (not to mention that newlines are represented by "\n" anyway).

So here's my solution.
I couldn't make it import and use an awk variable correctly :), but I did manage to get it to work by simply "unquoting" the variable. That is, the awk parts of the expression are in single quotes, and the bash variable is in double quotes.
Code:

while read line; do

  awk '/'"$line/"' {print "User:", $0; getline; print "Comment:", $0"\n"}' changes.txt > email.txt
  cat email.txt

done <usernames.txt

A real awk guru can probably clean it up even more.

David the H. 04-01-2010 01:15 PM

Stupid me. I was making things too complicated. Here's a way to do it through importing the bash variable into an awk variable (the -v option).

Code:

while read line; do

  awk -v ln="$line" '{if ($1==ln){print "User:", $0; getline; print "Comment:", $0"\n"}}' changes.txt > email.txt
  cat email.txt

done <usernames.txt

This format has the advantage in that it matches the username exactly.

berbae 04-01-2010 04:38 PM

Is not enough using grep to get what he wants ?
Code:

while read line; do
    grep --after-context=1 $line changes.txt
done <usernames.txt >email.txt


grail 04-02-2010 01:15 AM

Or you could just do it all in awk:

Code:

#!/usr/bin/awk -f

BEGIN{
    i = 0
    while( (getline line < ARGV[2]) > 0)
        arr[i++] = line
}

FILENAME == ARGV[1]{

    for (x in arr)
        if (arr[x] ~ $0)
            print arr[x]"\n"arr[x+1] >> "email.txt"

    print "" >> "email.txt"
}


dragonandante 04-05-2010 07:37 AM

Excellent, many thanks for the help everyone.


All times are GMT -5. The time now is 02:48 PM.