I\'m trying to look in a variable passed to my program (the variable is $1) and to replace any special characters with quoted forms of said special character, in order to no
The problem with what you've done is that you haven't quoted your sed
expressions. For example, write
sed s/\*/\\*/
either as
sed 's/\*/\\*/'
or
sed s/\*/\\\\*/
I'm not sure why do you need that elaborate function in order to escape special characters. You could define a function that would give back the escaped input string:
myescape() { printf "%q" "$1"; }
%q
causes
printf
to output the corresponding argument in a format that can be reused as shell input.
Another function for passing arguments to sed
:
myreplace() { sed "s/$1/$2/" <<< "$3"; }
Now you could invoke it by saying:
myreplace "$(myescape 'pattern')" "replacement" "original_string"
Example:
$ myescape() { printf "%q" "$1"; }
$ myreplace() { sed "s/$1/$2/" <<< "$3"; }
$ myreplace $(myescape 'a\^a*') 'test' 'aa\^a*aa[aaa]a'
atestaa[aaa]a
The purpose of the multiple invocations of sed
is to place a literal backsplash before each occurrence of a set of characters. This can be done in one call to sed
, but you need to be careful about how you specify the set.
First, let's see what the general command will look like:
newtarget=$( echo "$target" | sed -e 's/\([...]\)/\\\1/g'
where ...
will be replaced with the set of characters to escape. This commands uses parentheses to capture a single instance of one of those characters, the replaces it with a backsplash followed by the captured character. To specify the set of characters, use
[]*^+\.$[-]
Two notes: first, the ]
must come first so that it isn't mistaken for the end of the set, since []
is an invalid set. Second, -
must come last, so that it isn't mistaken as the range operator (e.g., [a-z]
is the set of lowercase letters, but [az-]
is simply the three characters a
, z
, and -
).
Putting it all together:
newtarget=$( echo "$target" | sed -e 's/\([]*^+\.$[-]\)/\\\1/g' )