
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, awk
dies 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 bar
gespeichert 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 IFS
ist 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 foo
und 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, $e
enthä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/sh
stehen. 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ßlichprint
ist nicht das, was Sie denken. Sie suchen nach printf
oder 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