sed special character replace not working in shell script

7,788

Solution 1

I don't think you are capturing the group right. Try this?

sed 's:\([]\[\^\$\.\*\/]\):\\\1:g'

Edit: nevermind, I wasn't aware of the relevance of &. The problem is you need to extra escape the slashes in replacement because of the parsing and passing to sub shell.

sed 's:[]\[\^\$\.\*\/]:\\\\&:g'

Also, if you used $(command) instead of backticks, you don't need the extra \'s

Solution 2

So the task is to write a sed substitution that escapes all special characters (defined as the characters []^$.*/, and I added \ too) in a string.

The substitution might look like

s/[][\^$.*/]/\\&/g

Note that we don't really have to escape any of the characters in the [...] set (the \ is treated literally too, so we can't escape anything in there), and that the only thing we have to make sure of is that ] is in the very beginning of it.

So the script (rewritten as a shell function, and revamped in other ways) becomes

function escape
{
    printf '%s\n' "$1" | sed 's/[][\^$.*/]/\\&/g'
}

Testing:

$ escape 'hello world'
hello world

$  escape '*.*'
\*\.\* 

$ escape '\/'
\\\/

$ escape '/\'
\/\\

$ escape 's/[][\^$.*/]/\\&/g'
s\/\[\]\[\\\^\$\.\*\/\]\/\\\\&\/g
Share:
7,788

Related videos on Youtube

drapkin11
Author by

drapkin11

Updated on September 18, 2022

Comments

  • drapkin11
    drapkin11 over 1 year

    I want to write a script 'test.sh' that will take a user's input and replace all special characters with a '\' + the character. My script:

    #!/bin/bash
    echo 'input='"$1"
    arg=`echo "$1" | sed 's:[]\[\^\$\.\*\/]:\\&:g'`
    echo 'modified input='"$arg"
    

    My command works on the string 'xy', which does not have any special characters. I run this in my terminal:

    test.sh xy
    

    And I obtain:

    input=xy
    modified input=xy
    

    However, when I run this:

    test.sh x.y
    

    I get:

    input=x.y
    modified input=x&y
    

    I don't understand why this script is not working. I expect to get:

    input=x.y
    modified input=x\.y
    

    I think the problem lies in this sed command but I'm not sure where:

    sed 's:[]\[\^\$\.\*\/]:\\&:g'
    
  • drapkin11
    drapkin11 over 11 years
    Yes, if I add two more '\' as you did will work. But I don't see why they are needed. Is there a reference you can point me to understand this? Also, not sure what you mean regarding $(command)
  • Drake Clarris
    Drake Clarris over 11 years
    enclosing commands in backticks uses simple substitution - so the the command is parsed by the current shell. $(command) opens a subshell, so anything inside the parens runs as if on its own command line. See for more info: wiki.bash-hackers.org/syntax/expansion/cmdsubst