sed ' in replacement text when $ in search pattern - bash

I have a file containing the string "this $c$ is a single quote", created as follows:
%echo "this \$c\$ is a single quote" > test3.txt
%cat test3.txt
this $c$ is a single quote
I would like to replace the letter c by a single quote, but I need to match the $ characters as well (to avoid matching other characters 'c'). I can't seem to do this.
I tried
%sed 's/$c$/$foo$/' test3.txt
this $c$ is a single quote
so obviously I need to escape the $.
%sed 's/\$c\$/$foo$/' test3.txt
this $foo$ is a single quote
But when I try to put an escaped ' in the replacement text I get
%sed 's/$c$/$\'$/' test3.txt
quote>
So I need to use some other quoting method.
%sed "s/\$c\$/$'$/" test3.txt
this $c$ is a single quote
Nothing was replaced, so let's try not escaping the $
%sed "s/$c$/$'$/" test3.txt
this $c$ is a single quote$'$
That was unexpected (to me), so let's try matching just the c as a sanity check.
%sed "s/c/'/" test3.txt
this $'$ is a single quote
I tried a number of other combinations but no luck. How do I do this in sed?

How about this?
!$ echo 'This is $c$ ceee' | sed s/\\\$c\\\$/\'/
This is ' ceee
I do not enclose the whole sed's command in quotes, so I need to escape each backslash and each dollar separately (and the quote as well, of course).
Edit
As Chris Lear points out, my replace string contains no dollars. Here is a fix – please note these dollars do not have a special meaning for sed (they are not interpreted as symbols for match, they're just plain characters to be inserted) so they can be escaped only once:
!$ echo 'This is $c$ ceee' | sed s/\\\$c\\\$/\\\$\'\\\$/
This is $'$ ceee
!$ echo 'This is $c$ ceee' | sed s/\\\$c\\\$/\$\'\$/
This is $'$ ceee

If you want to quote the sed command you need to do plenty of escaping. $ is a special character for both the shell and the sed patterns. In the shell it means the start of a variable name to expand, $c in your case. To sed it means the end of the line. To do the quoting you need to escape it from both of those so you could do
sed "s/\\\$c\\\$/\$'\$/" test3.txt
or you could mix your quoting styles to use single quotes around the $ expansions and double quotes around your single quote like
sed 's/\$c\$/$'"'"'$/' test3.txt

You can use ansi c string
sed $'s/\$c\$/\'/'
This allows single backslash escaping of $s and 's.
More info here
If you want to keep $s
sed $'s/\$c\$/$\'$/'

Try this :
sed -i -E "s/([$]c[$])/\'/g" sed.txt

Related

writing the values of variables to file. the value is got changed automatically

temp="This is the \\, example"
perl -pi -e "s/new.*/$temp/" tmp.txt
output:
cat tmp.txt
This is the \, example
In the above example the output should contain double \. but it contain only one \.
is there is any reason?
Backslash is the escape character inside double quotes. Use a single quote to disable escaping.
It's also an escape character in perl regexp and replacement strings, so you need to double it to make it expand literally.
temp='This is the \\\\, example'
perl -pi -e "s/new.*/$temp/" tmp.txt
temp= "new \\\\,"
cat tmp.txt
This is old Text
perl -pi -e "This.*/$temp/g" tmp.txt
cat tmp.txt
This is new\,Text
Still im getting same output after adding \\\\.

Trying to print "\n" in bash with sed

Having some problems having sed insert the two-character sequence \n. (I'm using bash to create some expect scripts). Anything that I try in a replace pattern ends up as an actual newline character.
I've tried:
sed s/<string>/'\\\\n'/
sed s/<string>/\\\\n/
sed s/<string>/\\n/
And pretty much any permutation that does or doesn't make any sense.
I need it to work with the bash and sed installed on a Mac.
sed s/<string>/'\\n'/ works for me with both the Lunix (GNU) and OS X (bsd) versions of sed:
$ echo aXb | sed s/X/'\\n'/
a\nb
sed s/<string>/\\\\n/ would also work. When bash sees \\ (outside of quotes), it treats it as a single escaped backslash, so \ is actually passed to the command. When it sees \\\\n, that's just two escaped backslashes followed by "n", so it passes \\n to the command. Then, when sed sees \\n, it also treats that as an escaped backslash followed by "n", so the replacement string winds up being \n. Since the "n" is always after any completed escape sequence, it's just treated as another character in the replacement string.
pure code, single quoted
sed 's/Pattern/\\n/' YourFile
Shell interpreted, double quote
sed "s/Pattern/\\\\n/" YourFile

How to grep for filename with literal backslash and apostrophe

I have a script which in which I am trying to grep a log file for lines containing filenames with apostrophes that have been escaped with a backslash.
My grep code is:
grep -i saved logfile | grep "/path/to/file/filename contains spaces, apostrophe\'s, and commas"
The apostrophes in the logfile all have a preceding backslash so the following grep command works:
grep -i saved logfile | grep "/path/to/file/filename contains spaces, apostrophe\\\'s, and commas"
However I am trying to run this in a if statement where the filename is a variable:
if [[ ! $(grep -i saved logfile | grep "$i") ]]
which doesn't return a match.
How can I escape the backslash and the apostrophe to get a match with grep?
There are multiple layers here. The backslash has a special meaning both to grep and in the shell inside double-quoted strings. Things are simpler if you put the regex in single quotes, but then, of course, the regex cannot contain a single quote. But you can have a single quote in double quotes adjacent to the single-quoted string.
grep -i saved logfile |
grep '/path/to/file/filename contains spaces, apostrophe\\'"'"'s, and commas'
The first single-quoted string ends with apostrophe\\' and is followed by "'" -- a double-quoted string containing a single quote. That in turn is followed by another single-quoted string.
Alternatively, add enough backslashes to satisfy both the shell and grep.
grep -i saved logfile |
grep "/path/to/file/filename contains spaces, apostrophe\\\'s, and commas"
Of course, another alternative is to use grep -F which will match the entire string as a literal, i.e. dots will only match dots, not any character, asterisks will only match asterisks, not repetitions of the previous character, etc.
(The correct plural of "apostrophe" is simply "apostrophes", though.)
grep'ing for "\\'" works for me:
root#ultra:~# a="\\\'"
root#ultra:~# echo -e marley\\\'s\ ghost\\nmarley\'s ghost
marley\'s ghost
marley's ghost
root#ultra:~# echo -e marley\\\'s\ ghost\\nmarley\'s ghost | grep $a
marley\'s ghost
root#ultra:~#

How to pass special characters through sed

I want to pass this command in my script:
sed -n -e "/Next</a></p>/,/Next</a></p>/ p" file.txt
This command (should) extract all text between the two matched patterns, which are both Next</a></p> in my case. However when I run my script I keep getting errors. I've tried:
sed -n -e "/Next\<\/a\>\<\/p\>/,/Next<\/a\>\<\/p>/ p" file.txt with no luck.
I believe the generic pattern for this command is this:
sed -n -e "/pattern1/,/pattern2/ p" file.txt
I can't get it working for Next</a></p> though and I'm guessing it has something to do with the special characters I am encasing. Is there any way to pass Next</a></p> in the sed command? Thanks in advance guys! This community is awesome!
You don't need to use / as a regular expression delimiter. Using a different character will make quoting issues slightly easier. The syntax is
\cregexc
where c can be any character (other than \) that you don't use in the regex. In this case, : might be a good choice:
sed -n -e '\:Next</a></p>:,\:Next</a></p>: p' file.txt
Note that I changed " to ' because inside double quotes, \ will be interpreted by bash as an escape character, whereas inside single quotes \ is just treated as a regular character. Consequently, you could have written the version with escaped slashes like this:
sed -n -e '/Next<\/a><\/p>/,/Next<\/a><\/p>/ p' file.txt
but I think the version with colons is (slightly) easier to read.
You need to escape the forward slashes inside the regular expressions with a \, since the forward slashes serve as delimiters for the regexes
sed -n -e '/Next<\/a><\/p>/,/Next<\/a><\/p>/p' file.txt

How to remove escape char from string in bash using sed?

I need to remove escape character from the string in bash. I get a data structure, which contains url paths with / escaped so I receive the regular link:
http://stackoverflow.com/questions/ask
as one with escaped /:
http:\/\/stackoverflow.com\/questions\/ask
Now I need to remove \ from the second link. For this purpose I tried using sed
`echo '"'${paths[$index]}'"' | sed "s#\\##g"`
But I get an error:
sed: -e expression #1, char 6: unterminated `s' command
If I replace \\ with ie. _ it works like a charm and removes all occurrences of _ in a string. How do I get rid of escape characters in a string using sed?
try this:
.......|sed 's#\\##g'
or:
.......|sed "s#\\\\##g"
EDIT add a test output:
kent$ echo "http:\/\/stackoverflow.com\/questions\/ask"|sed "s#\\\\##g"
http://stackoverflow.com/questions/ask
kent$ echo "http:\/\/stackoverflow.com\/questions\/ask"|sed 's#\\##g'
http://stackoverflow.com/questions/ask
Your question isn't clear about which way round you want so here is both ways:
$ sed 's#/#\\/#g' <<< "http://stackoverflow.com/questions/ask"
http:\/\/stackoverflow.com\/questions\/ask
$ sed 's#\\/#/#g' <<< "http:\/\/stackoverflow.com\/questions\/ask"
http://stackoverflow.com/questions/ask
You don't need to use sed.
paths[index]=${paths[index]//\\/}
or simply
echo ${paths[index]//\\/}
to see the result without modifying the value in-place.
You can use this :
sed 's#\\##g'
But the problem is when you encounter a backslash that you actually want in the string, but is escaped. In that case :
sed 's/\\\\/\x1/' |sed 's/[\]//g' | sed 's/\x1/\\/g'
Replaces the double backslash with with a temp character[SOH], replaces all other backslashes and then restores the backslash that is needed.

Resources