awk for-Schleife für jede Zeile in einer Datei

awk for-Schleife für jede Zeile in einer Datei

Ich muss herausfinden, wie ich eine Schleife durch eine Textdatei bekomme und für jede Zeile die Felder „Name“, „Projektnummer“ und „E-Mail“ nehme und sie in einer zu versendenden E-Mail-Vorlage ersetze.

Dies ist die Textdatei mit dem Namen send.txt:

Project 1,Jack,Chen,06,12,[email protected]
Project 2,Emily,Weiss,06,12,[email protected]
Project 3,Mary,Gonzalas,06,12,[email protected]

und dies ist die E-Mail-Vorlage namens Reminder.email:

Dear __FULLNAME__: 

This is a kindly reminder that our __Project__ meeting will be held on today. 

Best Regards, 
CIS5027

Für jede Zeile in der Textdatei muss ich in dieser E-Mail-Vorlage die Felder ersetzen vonVOLLSTÄNDIGER NAME: , UndProjekt. Mit den entsprechenden Werten kann ich das zwar für die erste Zeile machen, jedoch nicht für jede Zeile.

Das ist mein Skript

#

!/bin/sh
#Start your code from here

date= date "+%m/%d/%y"
print $date

#The following line is to scan a file called Event-member.data and return any lines with todays date and save them to a file called sendtoday.txt

grep -n $(date +"%m,%d") Event-member.data > sendtoday.txt

#The following line is to remove the first to characters of the file created above sendtoday.txt and output that to a file called send.txt.

cat sendtoday.txt | sed 's/^..//' > send.txt


#This is where im having trouble. When storing the values for the variables below of name, email, project #. The value of NR==1 thus it never goes through the rest of the lines. I've tried different solutions but none seem to work.

p=$(awk -F ',' 'NR==1{print $1}' send.txt)
n=$(awk -F ',' 'NR==1{print $2}' send.txt)
l=$(awk -F ',' 'NR==1{print $3}' send.txt)
e=$(awk -F ',' 'NR==1{print $6}' send.txt)

echo $p  $n  $l  $e

#This part is to replace the values in the email template using sed and save the modified template as sendnow.txt.  

sed -e "s/__FULLNAME__:/\ $n $l :/g;s/__Project__/\ $p /g" Reminder.email > sendnow.txt

cat sendnow.txt


#Yet to be written ... send out modified email templates.
exit 0

########

Dies ist die Ausgabe, die es erzeugt:

06/12/14
Project 1 Jack Chen [email protected]
Dear  Jack Chen : 

This is a kindly reminder that our  Project 1  meeting will be held on today. 

Best Regards, 
CIS5027

Wie Sie sehen, wurden die Felder richtig ersetzt, aber nur für Jack Chen. Die Datei send.txt enthielt 3 Zeilen, daher müssen 3 geänderte Versionen der obigen Vorlage vorhanden sein.

Antwort1

Es gibt keinen Grund, awkdies zu tun. Sie können es direkt in der Shell tun mitread. Das allgemeine Format ist , wobei das erste Feld als und der Rest jeder Zeile als read foo bargespeichert wird . In Ihrem Fall würden Sie also etwa Folgendes tun:$foo$bar

while IFS="," read p n l foo bar e; do 
    sed -e "s/__FULLNAME__:/\ $n $l :/g;s/__Project__/\ $p /g" Reminder.email; 
done < file

Dies IFSist der Eingabefeldtrenner, der, wenn er auf eingestellt ist, ,durch Kommas getrennte Felder liest. Dadurch können Sie jedes Feld nehmen und in einer Variablen speichern. Beachten Sie, dass ich zwei zusätzliche Variablen foound verwendet habe bar. Dies liegt daran, dass jedes Feld seinen eigenen Variablennamen benötigt und Sie 6 Felder haben. Wenn Sie nur 4 Variablennamen angeben, $eenthält der 4. () die Felder 4 bis 10.


Nun gibt es noch verschiedene andere Syntaxfehler in Ihrem Skript. Zunächst einmal ist die Shebang-Zeile falsch, Sie benötigen #! /bin/sh, es darf keine Leerzeile zwischen dem #!und dem /bin/shstehen. Außerdem muss für die Zuweisung desAusgabeeines Befehls an eine Variable zuzuweisen, müssen Sie var=`command`vorzugsweise das var=$(command)Format oder verwenden. Andernfalls wird der Variable der Befehl selbst als Zeichenfolge und nicht seine Ausgabe zugewiesen. Schließlichprintist nicht das, was Sie denken. Sie suchen nach printfoder echo. Eine bessere Möglichkeit, Ihr Skript zu schreiben, wäre also:

#!/bin/sh

date=$(date "+%m/%d/%y")
echo $date

## The following line is to scan a file called Event-member.data 
## and return any lines with todays date and save them to a file 
## called sendtoday.txt
grep -n $(date +"%m,%d") Event-member.data > sendtoday.txt

## The following line is to remove the first to characters of the file
## created above sendtoday.txt and output that to a file called
## send.txt. 
## I rewrote this to avoid the useless use of cat.
sed 's/^..//' sendtoday.txt > send.txt


## This is where you use read
while IFS="," read p n l foo bar e; do 
    sed -e "s/__FULLNAME__:/\ $n $l :/g;s/__Project__/\ $p /g" Reminder.email > sendnow.txt
    cat sendnow.txt
    ## This is where you need to add the code that sends the emails. Something
    ## like this:
    sendmail $e < sendnow.txt

done < send.txt

exit 0

########

Antwort2

Sie haben die Bedingung NR==1 verwendet NR==1{print $1}. Das bedeutet, dass die erste Zeile berücksichtigt wird send.txt. Verwenden Sie die Bedingung NR==2, um die zweite Zeile zu erhalten und so weiter. ODER verwenden Sie eine Schleife, um alle Zeilen durchzugehen, wie:

while read line
do
  p=`echo $line | awk -F '.' '{print $1}'`
  n=`echo $line | awk -F '.' '{print $2}'`
  l=`echo $line | awk -F '.' '{print $3}'`
  e=`echo $line | awk -F '.' '{print $1}'`

  sed -e "s/\__FULLNAME\__:/\ $n $l :/g;s/\__Project__/\ $p /g" Reminder.email > sendnow.txt

done<send.txt

Antwort3

vielleicht verpacken Sie Ihr Skript in etwas wie

for i in $(cat send.txt); do echo "line: $i"; done

?

Antwort4

cat xtmp |  awk '{s++; do_aything_you_want_here }'

**s++ geht jede Zeile durch **

cat xtmp
111
222
333
444

cat xtmp |  awk '{s++; print($1,"QQQ") }'
111 QQQ
222 QQQ
333 QQQ
444 QQQ

cat xtmp |  awk '{s++; print($1+3,"QQQ") }'
114 QQQ
225 QQQ
336 QQQ
447 QQQ

cat xtmp |  awk '{s++; for(i=1; i<=4 ; i++) print $1 }'  # this will repeat each line 4 time

cat tmp | awk '{s++; a=a+$1; print(s" "$1" "a)}' instead of a=a+$1 you can use a+=$1
1 111 111
2 222 333
3 333 666
4 444 1110

verwandte Informationen