replacing $ and # from file - shell

I have file with comments like this:
\$max_servers = 2;
\#\## BLOCKED ANYWHERE
I'm trying to
Replace all instances of \$ with $.
Replace all instances of \#\## with ###.
I wonder how I can go about doing that via sed or awk
What I have tried so far without much success using vi or vim
%s/^\//gc
%s/^#/\\/###/gc
Thank you

Another option to replace all [#$] in one pass is to use the following regular expression. The following is VI syntax:
:%s/\\\([$#]\)/\1/g
Replace the characters in the brackets [] with whatever you need if its more than just # and $.
The first \\ is a backslash - escaped since its inside a regular expression
The expression between the \( and \) is saved and later used in the replacement as \1.

Escaping backslash will work
#echo "\#\##"| sed "s/\\\\#\\\\##/###/g"
###
# echo "\\$"| sed "s/\\\\\\$/$/g"
$

In order to replace a backslash, you have to double it up, so it can quote itself much the way other special characters must be quoted. You can use sed instead of vim to help automate the process a bit:
$ sed -e 's/^\\\$/$/' -e 's/^\\#\\##/###/' $file > $new_file
Note that you have to put a backslash in front of dollar signs since they are used to mark an end of line in regular expressions. That's why I have \\\$ in my first expression. One backslash to quote the backslash and another backslash to quote the dollar sign.
By the way, these same sed expressions will also work inside Vim depending upon your Vim settings.

You escape special characters with the backslash. So for example, to replace everything with \$, you would do
%s/\\\$/$/g

sed 's|^\\\([$#]\)\\\{0,1\}|\1|' YourFile
work for your sample bu will also remove the 2 \ in \$\ ...,

Related

Escape twice special characters using sed

I have the following string variable defined in bash as version
Uploaded registry/version1.3.1
I need to escape the / twice so that the string looks like:
registry\\/version1.3.1
Is there a way to use sed to find and replace all / to \\/?
One backslash is used to change an argument to text or vice versa.
echo 'Uploaded registry/version1.3.1' | sed 's/\//\\\\\//g'
Uploaded registry\\/version1.3.1
In this case you need \\ for one backslash and \/for a slash.
Using sed
You need two backslashes, \\, in the RHS (right-hand side) of the sed command to replaces with a single backslash.
Also, it is a good idea to use a character other than / as a regex delimiter to avoid overescaping.
You can thus use
sed 's,/,\\\\/,g'
See this online demo:
echo 'Uploaded registry/version1.3.1' | sed 's,/,\\\\/,g'
# => Uploaded registry\\/version1.3.1
Using string manipulation
You may also just use string manipulation in Bash:
s='Uploaded registry/version1.3.1'
echo "${s//\//\\\\\/}"
# => Uploaded registry\\/version1.3.1
Here, the backslash needs doubling again, and a single \ is added to escape /s. Note that "${s//a/b} means: replace all occurrences of a with b in s variable.

Why would sed have trouble seeing my PS1 prompt?

I'm trying to use sed as root to alter the default PS1.
The first 2 lines were just to make sure I had the syntax structured right and to see if the quotation marks made a difference,
running them consecutively allows me to change a comment near the top of the file and then change it back.
Opening the file in nano confirms the changes are effective, which should rule out 'write permissions'.
sed -i 's/If not running interactively,/stringtoreplaceitwith/' /etc/skel/.bashrc
sed -i "s/stringtoreplaceitwith/If not running interactively,/" /etc/skel/.bashrc
sed -i "s/\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ /Replace PS1/" /etc/skel/.bashrc
I'm not sure if it's something else about the string's structure,
but for some reason, it's not finding what I'd like to substitute.
\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
(with a trailing blank).
Your problem is due to quoting and escaping. Let's reduce the string you're trying to substitute to just this:
\w\[\033[00m\]\$
(with a trailing blank) – this contains all the difficulties, but is less verbose.
To match this, we have to
escape all the backslashes: \w becomes \\w etc.
escape [ and ], because they're special to sed: [ becomes \[, and \[ becomes \\\[ (escaped backslash, escaped [)
escape $: \$ becomes \\\$
Then, we have to use single quotes around our sed command so the shell doesn't modify the string:
$ sed 's/\\w\\\[\\033\[00m\\\]\\\$ /Replace PS1/' <<< '\w\[\033[00m\]\$ '
Replace PS1
It can also work with double quotes, but then we have to add another round of escaping for the shell: \[ becomes \\\[ (escaped for sed) becomes \\\\\\[ (escaped for the shell), and so on.
$ sed "s/\\\\w\\\\\\[\\\\033\\[00m\\\\\\]\\\\\\$ /Replace PS1/" <<< '\w\[\033[00m\]\$ '
Replace PS1
Double quoting only makes sense if you're using variables, though, for obvious reasons.
Finally, for your actual string:
$ echo '\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' \
| sed 's/\\\[\\033\[01;32m\\\]\\u#\\h\\\[\\033\[00m\\\]:\\\[\\033\[01;34m\\\]\\w\\\[\\033\[00m\\\]\\\$ /Replace PS1/'
Replace PS1

Replace Double quotes with space

this is perhaps one of the most discussed topics here. I tried almost all the commands and other tweaks found here, but something doesn't seems to be doing well.
i would want to replace all the double quotes in my file with whitespace/blank
I'm seeing the below error when i tried to execute this command.
sed "s/"/ \''/g' x_orbit.txt > new.tx
sed: -e expression #1, char 3: unterminated `s' command
You're close. Just use single quotes, so the shell doesn't try to expand the metacharacters in your sed command:
sed 's/"/ /g' x_orbit.txt > new.txt
You could try tr for example:
tr '"' ' ' < x_orbit.txt > new.txt
The script you provided:
sed "s/"/ \''/g' x_orbit.txt > new.tx
means:
sed # invoke sed to execute the following script:
" # enclose the script in double quotes rather than single so the shell can
# interpret it (e.g. to expand variables like $HOME) before sed gets to
# interpret the result of that expansion
s/ # replace what follows until the next /
" # exit the double quotes so the shell can now not only expand variables
# but can now do globbing and file name expansion on wildcards like foo*
/ # end the definition of the regexp you want to replace so it is null since
# after the shell expansion there was no text for sed to read between
# this / and the previous one (the 2 regexp delimiters)
\' # provide a blank then an escaped single quote for the shell to interpret for some reason
'/g' # enclose the /g in single quotes as all scripts should be quoted by default.
That is so far off the correct syntax it's kinda shocking which is why I dissected it above to try to help you understand what you wrote so you'll see why it doesn't work. Where did you get the idea to write it that way (or to put it another way - what did you think each character in that script meant? I'm asking as it indicates a fundamental misunderstanding of how quoting and escaping works in shell so it'd be good if we could help correct that misunderstanding rather than just correct that script.
When you use any script or string in shell, simply always enclose it in single quotes:
sed 'script' file
var='string'
unless you NEED to use double quotes to let a variable expand and then use double quotes unless you NEED to use no quotes to let globbing and file name expansion happen.
An awk version:
awk '{gsub(/"/," ")}1' file
gsub is used for the replace
1 is always true, so line is printed

BSD sed; error "unescaped newline inside substitute pattern" when run from script

I am attempting to use (BSD) sed to modify my /etc/gettytab. The goal is to modify this entry:
P|Pc|Pc console:\
:ht:np:sp#9600:
to this entry:
P|Pc|Pc console:\
:ht:np:sp#115200:\
:cl=\E[H\E[2J:
If I issue the command below (it's on two lines), it works perfectly.
# sed -in ' /P|Pc|Pc console/,/^#/ s/9600:/115200:\\\\
:cl=\E[H\E[2J:/' /etc/gettytab
However, if I use the exact same command (literally copy/paste it) in a script, I get an error message:
sed: 1: " /P|Pc|Pc console/,/^#/ ...": unescaped newline inside substitute pattern
Searching, I found this post: unescaped newline inside substitute pattern which talks about the trailing /, but I have that in my pattern.
If anyone can assist with what I am doing wrong, I would greatly appreciate it.
Within your script, you escape newlines with a \, and you escape the \ that you're embedding into your output so that it will be interpreted literally. If my math is right, that comes to THREE, not four backslashes.
$ cat i
P|Pc|Pc console:\
:ht:np:sp#9600:
$ cat i.sh
#!/bin/sh
# ┏━━━ escapes the next character,
# ┃┏━━ literal backslash for output,
# ┃┃┏━ escapes the newline.
sed -ne '/^P|/,/^#/ s/9600:/115200:\\\
:cl=\E[H\E[2J:/' -e p i
$ ./i.sh
P|Pc|Pc console:\
:ht:np:sp#115200:\
:cl=E[HE[2J:
$

Unix shell replacing a word containing backtick in a file

I am having a sql file (samplesqlfile) and I want to replace a string which contains backticks with another string. Below is the code.
actualtext="FROM sampledatabase.\`Datatype\`"
replacetext="FROM sampledatabase.\`Datatype_details\`"
sed -i "s/\<${actualtext}\>/${replacetext}/g" samplesqlfile
This is not working. The actual word to be replaced is
FROM sampledatabase.`Datatype`
I added back slashes to escape the backticks. But still it is not working. Please help.
Observe that this does not work:
$ sed "s/\<${actualtext}\>/${replacetext}/g" samplesqlfile
FROM sampledatabase.`Datatype`
But this does:
$ sed "s/\<${actualtext}/${replacetext}/g" samplesqlfile
FROM sampledatabase.`Datatype_details`
The problem was the \>. The string variable $actualtext does not end with a word-character. It ends with a quote. Consequently, \> will never match there. The solution is to remove \>.
To clarify, \> matches at the boundary between a word character and a non-word character where the word character appears first. Word characters can be alphanumerics or underlines.
\> is a GNU extension. The behavior under BSD/OSX sed will be different.
For purposes of illustration here, I removed the -i option. For your intended use, of course, add it back.

Resources