sed - shell script to replace a keyword in a file with the contents of another file

07
2014-07
  • Jem

    I'm to create a .sh to replace a specific keyword in a file using the contents of an other file.

    • template.html contains a unique string "PLACEHOLDER"
    • it must be replaced with the contents of file "contents.html"

    Sed can be used to replace the keyword:

    value="hello superuser"
    sed -e "s/__PLACEHOLDER__/${value}/g" template.html > page.html
    

    So I tried the following:

    value=$(<contents.html)
    sed -e "s/__PLACEHOLDER__/${value}/g" template.html > page.html
    

    And get the following error message: unescaped newline inside substitute pattern

    How to handle this sort of situation please?

    Thanks!

  • Answers
  • glenn jackman

    With bash, you could write:

    templ=$(<template.html)
    value=$(<contents.html)
    echo "${templ//__PLACEHOLDER__/$value}" > page.html
    
  • Kenneth L

    This is because "contents.html" contains multiple lines, and the newline characters have to be converted into \n before feeding to sed.

    For example if "contents.html" contains

    Line 1
    Line 2
    Line 3
    

    You will need to change it to `Line 1\nLine2\nLine3" before using it as the substitute pattern.

    I changed your script as:

    value=$(sed ':a;N;$!ba;s/\n/\\n/g' contents.html)
    sed -e "s/__PLACEHOLDER__/${value}/g" template.html > page.html
    

    The first line reads "contents.html" and replace newline character with \n. (Credit to this thread)


  • Related Question

    editing - Using sed to replace text from a list of files from find
  • Kyle Hayes

    Given the following find command: find . | xargs grep 'userTools' -sl

    How can I use sed on the results of that command?

    output:

    ./file1.ext
    ./file2.ext
    ./file3.ext
    

  • Related Answers
  • garyjohn

    I am assuming that you want to perform some sed operation on the contents of each of the files rather than on the list of file names since you seem to know how to do that already. The answer depends in part on the version of sed you have available. If it supports the -i option (edit files in place), you could use xargs again like this:

    find . | xargs grep 'userTools' -sl | xargs -L1 sed -i 's/this/that/g'
    

    If your sed doesn't have the -i option, you could do this instead:

    find . | xargs grep 'userTools' -sl | while read file
    do
    sed 's/this/that/g' "$file" > tmpfile
    mv tmpfile "$file"
    done
    
  • Dennis Williamson
    find . -print0 | xargs -0 grep -slZ 'userTools' | xargs -0 sed -i 's/foo/bar/'
    

    or

    find . -print0 | xargs -0 sed -i '/userTools/ s/foo/bar/'
    

    or

    ack -l --print0 'userTools' | xargs -0 sed -i 's/foo/bar/'
    
  • slhck
    find \Path_where_files_are -type f -name 'file_type' -exec  sed -e 's/"text_to_be_changed"/"text_to_be_changed_to"/' {} +