views:

59

answers:

1

This script will read an old and a new value from the user and then use sed to find and replace them in a file. For example if I entered T*T*z and B*B*z it would look for T\*T\*z in the file and replace with B\*B\*z. It works but I've been trying to make this more concise.

I don't have any need for the intermediate variables $ESC_OLD_PW and $ESC_NEW_PW. Is there a more sensible way to do this?

    #!/bin/bash
    read -sp "Old:" OLD_PW && echo
    read -sp "New:" NEW_PW && echo

    # Add escape characters to what user entered
    printf -v ESC_OLD_PW "%q" "${OLD_PW}"
    printf -v ESC_NEW_PW "%q" "${NEW_PW}"

    # Escape again for the sed evaluation.
    printf -v ESC_ESC_OLD_PW "%q" "${ESC_OLD_PW}"
    printf -v ESC_ESC_NEW_PW "%q" "${ESC_NEW_PW}"

    sed -i -e s/"${ESC_ESC_OLD_PW}"/"${ESC_ESC_NEW_PW}"/g $1

I've tried the following:

    ~$ OLD_PW="T*T*z"
    ~$ printf "%q" $OLD_PW | xargs printf "%q"
    printf: %q: invalid conversion specification
    ~$

And I've tried many variations on piping things into printf... Any suggestions?

A: 

Intermediate variable-free:

sed -i -e "s/$(printf '%q' $(printf '%q' $OLD_PW))/$(printf '%q' $(printf '%q' $NEW_PW))/g" $1
Matthew Flaschen
AHA! printf '%q' $(printf '%q' $OLD_PW) THX!!xargs fails me again. or did I fail it? it is such a trying relationship...
Jeff
@Jeff, the reason your xargs doesn't work is that GNU printf doesn't support %q. GNU bash's built-in printf does, though. This is a bit odd, but you should keep in mind %q is non-standard.
Matthew Flaschen
@Jeff: That's correct. In your last example the first `printf` is calling Bash's, but `xargs` calls the external `/usr/bin/printf`.
Dennis Williamson