awk for loop para cada linha em um arquivo

6

Eu preciso descobrir como obter um loop em um arquivo de texto e, para cada linha, usar os campos name, project # e email, e substituí-los em um modelo de email a ser enviado.

Então este é o arquivo de texto chamado 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]

e este é o modelo de email chamado Reminder.email:

Dear __FULLNAME__: 

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

Best Regards, 
CIS5027

Assim, para cada linha do arquivo de texto, eu preciso substituir neste modelo de email os campos FULLNAME : e Projeto . Com os valores correspondentes que eu posso fazer para a primeira linha, no entanto, não posso fazer isso para cada linha.

Este é o meu script

#

!/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

########

Esta é a saída que produz:

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

Como você vê, ele substituiu os campos corretamente, mas apenas para Jack Chen. Havia 3 linhas no arquivo send.txt, portanto, deve haver 3 versões modificadas do modelo acima.

    
por S0urc3 12.06.2014 / 09:51

3 respostas

6

Não há razão para usar awk para isso. Você pode fazer isso diretamente no shell usando read . O formato geral é read foo bar , que salvará o primeiro campo como $foo e o restante de cada linha como $bar . Então, no seu caso, você faria algo como:

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

O IFS é o separador do campo de entrada que, quando definido como , , lê os campos delimitados por vírgulas. Isso permite pegar cada campo e armazená-lo em uma variável. Observe que usei duas variáveis extras foo e bar . Isso ocorre porque cada campo precisa de seu próprio nome de variável e você tem 6 campos. Se você der apenas 4 nomes de variáveis, o quarto ( $e ) conterá os campos 4 até o último.

Agora, existem vários outros erros de sintaxe no seu script. Primeiro de tudo, a linha shebang está errada, você precisa de #! /bin/sh , não pode haver uma linha em branco entre o #! e o /bin/sh . Além disso, para atribuir a saída de um comando a uma variável, você precisa usar o formato var='command' ou, preferencialmente var=$(command) . Caso contrário, o próprio comando como uma string e não sua saída será atribuído à variável. Por fim, print não é o que você acha que é. Você está procurando por printf ou echo . Então, uma maneira melhor de escrever seu roteiro seria:

#!/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

########
    
por 12.06.2014 / 10:48
3

Você usou NR == 1 condição NR==1{print $1} . Isso significa que ele considerará a primeira linha de send.txt . Use a condição NR == 2 para obter a segunda linha e assim por diante. OU use o loop para percorrer todas as linhas como

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
    
por 12.06.2014 / 10:57
1

talvez envolva seu script em algo como

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

?

    
por 12.06.2014 / 10:47