Can't scape backslashes with sed - linux

I'm trying to find \STRING1\ and replace it with \STRING2\ (mind the backslashes)
I tried the following:
find ./ -type f -exec sed -i "s/\\STRING1\\/\\STRING2\\/g" {} \;
It didn't work and I got this error: sed: -e expression #1, char 21: unterminated `s' command
I searched the web and people recommend adding two backslashes to any backslash I'd like to search and/or replace. So I tried this:
find ./ -type f -exec sed -i "s/\\\STRING1\\\/\\\STRING2\\\/g" {} \;
I got no errors this time, but it didn't do anything. What's the issue?

Use single quotes:
> echo "some text\STRING1\ and some more \STRING1\andeven more" | sed 's/\\STRING1\\/\\STRING2\\/g'
some text\STRING2\ and some more \STRING2\andeven more

If you want to quote your sed command with double quotes, then you have to use quadruple backslashes to get a single literal backslash in the pattern:
find ./ -type f -exec sed -i "s/\\\\STRING1\\\\/\\\\STRING2\\\\/g" {} \;
This is because backslash is a live metacharacter for double-quoted shell strings, so the shell cuts the number of backslashes in half and then so does sed. Alternatively, use single quotes as suggested in the other answer.

You need to use a single quoted string.
If you use double quotes, the string is preprocessed by your shell and sed receives only single backslashes.

Related

How to replace a text string with dollar sign $ in Linux?

I am trying to replace a text '../../Something' with '$Something' in all .txt files in current directory.Let me know where I am going wrong?
find . -name "*.txt" | xargs sed -i "s/..\/..\/Something/\'\$Something'/g"
Error - Variable name must contain alphanumeric character
I also tried with but doesn't work-
find . -name "*.txt" | xargs sed -i "s/..\/..\/Something/\\$Something/g"
Any suggestions for correct command?
You're shell is treating the $ as the start of a variable.
There are two ways you can make it work:
Use single quotes, which tells the shell to not perform any variable interpolation (among other things):
find . -name "*.txt" | xargs sed -i 's/..\/..\/Something/\$Something/g'
Escape the $ from the shell and sed. This requires 3 backslashes (the first one escapes the second backslash, the second escapes the dollar sign once the tring reaches sed, and the third escapes the dollar sign in the shell so it doesn't get treated as a variable):
find . -name "*.txt" | xargs sed -i s/..\\/..\\/Something/\\\$Something/g
You can try removing the extra backslash given in the second command.
find . -name "*.txt" | xargs sed -i 's/../../Something/\$Something/g'
Tested the following and it worked for me. Let me know if this works
find . -name "*.txt" | xargs sed -i "s,../../Something,$\Something,g"

Using sed editor to replace a string containing backslash [duplicate]

This question already has answers here:
How to insert strings containing slashes with sed? [duplicate]
(11 answers)
Closed 5 years ago.
How can i use the sed to replace string containing backslash "\" is all files of specific directory.
I tried this but wont work for me
find /home/tds/nfb -type f -exec sed -i 's//var/www/tds///home/tds//' {} \;
I want to replace "/var/www/tds/" with "/home/tds/"
You can do
find /home/tds/nfb -type f -exec sed -i 's|/var/www/tds/|/home/tds/|' {} \;
where the delimiter / is replaced by |. (sed can use almost any character as a delimiter -- it picks whatever character follows the s). Alternatively, you could escape all your backslashes as follows and still used \:
sed -i 's/\/var\/www\/tds\//\/home\/tds\//'

Why are the backslash and semicolon required with the find command's -exec option?

I have begun to combine different commands in the linux terminal. I am wondering why the backslash and semicolon are required for a command such as:
find ./ -name 'blabla' -exec cp {} ./test \;
when a simple cp command is simply:
cp randomfile ./test
without the \;
Are they to clearly indicate the end of a command, or is it simply required in the documentation? What is the underlying principle?
The backslash before the semicolon is used, because ; is one of list operators (or &&, ||) for separating shell commands. In example:
command1; command2
The find utility is using ; or + to terminate the shell commands invoked by -exec.
So to avoid special shell characters from interpretation, they need to be escaped with a backslash to remove any special meaning for the next character read and for line continuation.
Therefore the following example syntax is allowed for find command:
find . -exec echo {} \;
find . -exec echo {} ';'
find . -exec echo {} ";"
find . -exec echo {} \+
find . -exec echo {} +
See also:
Using semicolon (;) vs plus (+) with exec in find
Simple unix command, what is the {} and \; for
from "man find":
All following
arguments to find are taken to be arguments to the command until
an argument consisting of ';' is encountered.
find needs to know when the arguments of exec are terminated. It is natural to terminate a shell command with ; because also the shell uses this character. For the very same reason such a character must be escaped when inserted through the shell.

What's the proper escaping of the following string for find and replace?

I'm trying to use the following instructions
http://www.brunolinux.com/02-The_Terminal/Find_and%20Replace_with_Sed.html
To replace all occurrences of
<BASE href="file://C:\Users\J\Documents\Personal\J\">
with nothing. I have tried
find . -type f -exec sed -i 's/<BASE href=\"file:\/\/C:\\Users\\J\\Documents\\Personal\\J\\">//g' {} \;
But it's not working likely because something is wrong with escaping characters. What have I done wrong?
Changing the substitution delimiter helps a lot:
find . -type f -exec sed -i \
's!<BASE href="file://C:\\Users\\J\\Documents\\Personal\\J\\">!!g' {} \;
try with this:
s/\<BASE href\="file:\/\/C:\\Users\\J\\Documents\\Personal\\J\\\"\>//g
or try with perl with the same same command i.e.,
instead of sed -i use perl -pi

Sed replacement not working when using variables [duplicate]

This question already has answers here:
Replace a string in shell script using a variable
(12 answers)
Closed 9 years ago.
something strange is happening when trying to replace string with sed. This works :
find /home/loni/config -type f -exec sed -i 's/some_pattern/replacement/g' {} \;
So it works when I manually type the strings. But in the case below replacement doesn't occur :
find /home/loni/config -type f -exec sed -i 's/${PATTERN}/${REPLACEMENT}/g' {} \;
When I echo these two variables PATTERN and REPLACEMENT they have the correct values.
I'm trying to replace all occurences of pattern string with replacement string in all files in my config directory.
Try
find /home/loni/config -type f -exec sed -i "s/${PATTERN}/${REPLACEMENT}/g" {} \;
instead. The ' quotes don't expand variables.
Not sure if I got this right, but if you want to replace the ${PATTERN} with ${REPLACEMENT} literally you have to escape the dollar and maybe the braces, those are reserved characters in regular expressions:
find /home/loni/config -type f -exec sed -i -e 's/\$\{PATTERN\}/\$\{REPLACEMENT\}/g' {} \;

Resources