You are not logged in.
Hi,
I wrote the following script to create an addressbook in the form
Name 1 <Email 1>
..
Name n <Email n>
from vcf files to be used by dmenu.
Here is what I came up with:
#!/usr/bin/bash
ADDRESSES="file_1.vcf ... file_n.vcf"
for a in $ADDRESSES; do
IFS=$'\n'
for line in $(egrep '(^EMAIL|^FN)' $a); do
case $line in
FN*)
name=$(echo $line | cut -d':' -f2)
;;
EMAIL*)
mail=$(echo $line | cut -d':' -f2)
echo "$name"
echo "$mail"
;;
esac
done
done
Which works perfectly fine and prints
Name 1
E-Mail 1
...
Name n
E-Mail n
as expected. But if I replace the two echo lines with just
echo "$name $mail"
the output always is just a space and the email address. It seems like, $name just became empty but it really doesn't make any sense for me. Do you know the answer?
Last edited by null (2015-07-31 17:18:26)
Offline
I'm pretty sure your .vcf files contain DOS line endings (i.e., CR LF). This means there's a CR at the end of $name which returns the cursor to the beginning of the line. As a result, $mail overwrites $name when printed directly to a terminal.
Offline
Year. Just figured it out myself. Solved by applying
sed 's/\r$//'
after the egrep.
But thanks
Offline
FWIW, that entire loop and everything in it could be replaced by awk:
awk -F ':' '
/^FN/ { name=$2; }
/^EMAIL/ { mail=$2; }
/^END:VCARD/ { printf "%s %s\n", name, mail; }
' $ADDRESSES
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
It probably can, but not by your script. One of the *.vcf files is the sync of my mobile phone and got a lot of contacts without mail addresses and also a few contacts with serveral addresses. Your script doesn't produce anything remotely usefull for me. But I would welcom a working awk solution
Offline
It should do the same thing as yours: it finds every line starting with FN or EMAIL and is stores what comes after FN in "name" and what comes after EMAIL as "mail". The one thing I changed was that it wait's for a line starting with END:VCARD before it prints the pair. It could just print them in the EMAIL block and it would exactly duplicate the behavior of your script:
awk -F ':' '
/^FN/ { name=$2; }
/^EMAIL/ { printf "%s %s", name, $2; }
' $ADDRESSES
But I'm just guessing here as I don't have the input. The point remains that awk just seems like a much cleaner approach.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
I don't really know awk so I can only guess but doesn't you solution lack the overwriting of $name? Because FN always comes before EMAIL I always write the most recent name into $name and only use it, if I get one or more email addresses.
Your first solution seems to always print the last e-mail address for every new contact without email address:
# awk -F ':' '
/^FN/ { name=$2; }
/^EMAIL/ { mail=$2; }
/^END:VCARD/ { printf "%s %s\n", name, mail; }
' addresses.vcf | wc -l
100
# egrep -c '^FN:' addresses.vcf
100
# egrep -c '^EMAIL;' addresses.vcf
35
# ./myscript.sh | wc -l
35
Your second solution doesn't print anything for me.
While I agree that awk seems like a much cleaner approach I did it in bash because I just wanted it to work quickly and I find awk code rather hard to write and to read if it comes to things like 'save the most recent name and print it with every email address until next name'..
Last edited by null (2015-07-31 18:51:35)
Offline
But I'm just guessing here as I don't have the input.
This. Trilby is trying to help; you could learn awk, give us the input so we could do it for you, or do it with your script if it works for you. In any event this back-and-forth as it is doesn't really help, IMO.
Offline
While I agree that awk seems like a much cleaner approach I did it in bash because I just wanted it to work quickly and I find awk code rather hard to write and to read if it comes to things like 'save the most recent name and print it with every email address until next name'..
Then go with what works. I just love awk - and I have a bit of OCD when it comes to scripting: I hate wasted processes. But in reality this is just pointless OCD as little scripts like this aren't really resource-critical.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Trilby wrote:But I'm just guessing here as I don't have the input.
This. Trilby is trying to help; you could learn awk, give us the input so we could do it for you, or do it with your script if it works for you. In any event this back-and-forth as it is doesn't really help, IMO.
I thought it was obvious that I was satisfied with my script but would welcome a working awk solution (because yeah. I also prefere one process to many for the same job).
Which doesn't mean that I want to learn awk right now nor that I want to share private *.vcf files or create new ones with the same structure..
Thanks @Trilby for your input
Edit: two years later:
awk -F ':' '/^(EMAIL|FN)/{gsub(/\r$/, ""); if ($1=="FN") n=$2; else print n,$2 }' $FILE
does the trick..
Last edited by null (2018-01-04 20:21:58)
Offline