Search code examples
bashshellsedexpansion

SED expansion not working even with double quotes in bash script


Having a little trouble with a bash shell script. Basically, I am inserting values into a file and then creating a variable from it and attempting to append and expand the variable values in another file via sed.

i.e:

cat animal.txt
Dog: 5
Ferret: 1
Cat: 10
Hamster: 2
NUM=$(cat animal.txt)

I want to then append the values from the variable 'NUM' to another file temp.txt:

cat temp.txt
country: England  city: Manchester
country: England  city: Hull
country: England  city: Liverpool
country: England  city: London

Tried all these variations but none suffice:

sed 's/$/'"${NUM}"'/' temp.txt
sed 's/$/"${NUM}"/' temp.txt
sed 's/$/'"${NUM}"'/' temp.txt
sed "s/$/"${NUM}"/" temp.txt
sed "s/$/\${NUM}\/" temp.txt

These two somewhat work but the variable is still never expanded:

sed 's/$/"${NUM}"/' temp.txt
sed 's/$/"\${NUM}\"/' temp.txt
country: England  city: Manchester  "${NUM}"
country: England  city: Hull  "${NUM}"
country: England  city: Liverpool  "${NUM}"
country: England  city: London  "${NUM}"

Even if I enclose the entire expression in double-quotes as such:

sed "s/$/${NUM}/" temp.txt
sed "s/$/\${NUM}\/" temp.txt

I get:

sed: -e expression #1, char 27: unterminated `s' command
sed: -e expression #1, char 12: unterminated `s' command

Desired Output:

country: England  city: Manchester  Dog: 5
country: England  city: Hull        Ferret: 1
country: England  city: Liverpool   Cat: 10
country: England  city: London      Hamster: 2

or

country: England  city: Manchester  Dog:     5
country: England  city: Hull        Ferret:  1
country: England  city: Liverpool   Cat:     10
country: England  city: London      Hamster: 2

I understand I should avoid single quotes and use double quotes but what am I missing? Is sed the wrong tool to work with here? and do you think awk would be better?

Thank you.


Solution

  • Is sed the wrong tool to work with here? Yes probably.

    Anyway, if your animals.txt file is small enough, you could get away with this statement.

    $ NUM="$(cat animal.txt)"; IFS=$'\n'; n=1; for num in $NUM; do i=0; while read -r line; do i=$((i + 1)); if [ $i -eq $n ]; then echo "$line" "$num"; n=$((n + 1)); break; fi; done < temp.txt; done
    
    country: England  city: Manchester Dog: 5
    country: England  city: Hull Ferret: 1
    country: England  city: Liverpool Cat: 10
    country: England  city: London Hamster: 2
    

    But for large file size, awk is probably a better choice.

    $ awk 'NR==FNR {num[FNR]=$0;next}{print $0 " " num[FNR]}' animal.txt temp.txt
    
    country: England  city: Manchester Dog: 5
    country: England  city: Hull Ferret: 1
    country: England  city: Liverpool Cat: 10
    country: England  city: London Hamster: 2