how can we use sed command to write \n in a file? - linux

When replacing string in file with other string having \n then when it replace it enters a line rather then writing \n in shell.
program-
string="status=\"translated\">NIRANJAN\\nKUMAR"
sed -i 's/status="translated">/'"$string"' /g' text.txt
text files contains- status="translated">Fixes
output is:
status="translated">NIRANJAN
KUMAR
but i want status="translated">NIRANJAN\nKUMAR
please suggest me the steps. Thanks :)

You already lost some backslashes during this assignment:
string="status=\"translated\">NIRANJAN\\nKUMAR"
The \\ will be reduced to a single \, so you end up with \n in your sed command, resulting in a newline (on some versions of sed, at least).
To preserve them, use single quotes around the string literal:
string='status="translated">NIRANJAN\\nKUMAR'
Now your sed command should behave as you expect.

Related

How to correctly detect and replace apostrophe (') with sed?

I'm having a directory with many files having special characters and spaces. I want to perform an operation with all these files so I'm trying to store all filenames in a list.txt and then run the command with this list.
The special characters in my list are & []'.
So basically I want to use sed to replace each occurence with \ + the character in question.
E.g. : filename .txt => filename\ .txt etc...
The thing is I have trouble handling apostrophes.
Here is my command as of now :
ls | sed 's/\ /\\ /g' | sed 's/\&/\\&/g' | sed "s/\'/\\'/g" | sed 's/\[/\\[/g' | sed 's/\]/\\]/g'
At first I had issues with, I believe, the apostrophes in the string command in conflict with the apostrophes surrounding the string. So I used double quotes instead, but it still doesn't work.
I've tried all these and nothing worked :
sed "s/\'/\\'/g" (escaping the apostrophe)
sed "s/'/\'/g" (escaping nothing)
sed "s/'/\\'/g" (escaping the backslash)
sed 's/"'"/\"'"/g' (double quoting single quote)
As a disclaimer, I must say, I'm completely new to sed. I just run my first sed command today, so maybe I'm doing something wrong I didn't realize.
PS : I've seen those thread, but no answer worked for me :
https://unix.stackexchange.com/questions/157076/how-to-remove-the-apostrophe-and-delete-the-space
How to replace to apostrophe ' inside a file using SED
This may do:
cat file
avbadf
test&rr
more [ yes
this ]
and'df
sed -r 's/(\x27|&|\[|\])/\\\1/g' file
avbadf
test\&rr
more \[ yes
this \]
and\'df
\x27 is equal to singe quote '
\x22 is equal to double quote "
Whoops, I found the answer to my question. Here is the working input :
sed "s/'/\\\'/g"
This will effectively replace any ' with \'.
However I'm having trouble understanding exactly what's happening here.
So if I understand correctly, we are escaping the backslash and the apostrophe in the replacement string. Now, if somebody could answer some those, I would be grateful :
Why don't we need to escape the first quote (the one in the pattern to find) ?
Why do we have to escape the backslash whereas for the other characters, there's no need ?
Why do we need to escape the second quote (the one in the replacement string) ?
I think all of your sed matches actually need that replacement pattern. This one seems to work for all examples:
ls | sed "s/\ /\\\ /g" | sed "s/\&/\\\&/g" | sed "s/\[/\\\[/g" | sed "s/\]/\\\]/g" | sed "s/'/\\\'/g"
So it is s/regex/replacement/command and 'regex' and 'replacement' have different sets of special characters.
The only one that's different is s/'/\\\'/g and there only because I don't believe there is any special ' character on the regex expression. There is some obscure \' special character in the replacement expression, for matching buffer ends in multi-line mode, accord to the docs. That might be why it needs an escape in the replacement side, but not in the regex side.
For example, \5 is a special character in the replacement expression, so to replace:
filename5.txt -> filename\5.txt
You would also need, as with apostrophe:
sed "s/5/\\\5/g"
It probably has to do with the mysterious inner works of sed parsing, it might read from right to left or something.
Please try the following:
sed 's/[][ &'\'']/\\&/g' file
By using the same example by #Jotne, the result will be:
gavbadf
gtest\&rr
gmore\ \[\ yes
gthis\ \]
gand\'df
[How it works]
The regex part in the sed s command above just defines a character
class of & []', which should be escaped with a backslash.
The right square bracket ] does not need escaping when put
immediately after the left square bracket [.
The obfuscating part will be the handling of a single quote.
We cannot put a single quote within single quotes even if we escape it.
The workaround is as follows: Say we have an assignment str='aaabbb'.
To put a single quote between "aaa" and "bbb", we can say as
str='aaa'\''bbb'.
It may look puzzling but it just concatenates the three sequences;
1) to close the single-quoted string as 'aaa'.
2) to put a single quote with an escaping backslash as \'.
3) to restart the single-quoted string as 'bbb'.
Hope this helps.

SED: Insert a string with special character

I want to INSERT a string with "'" as special character in multiple files. All the files in which I want to insert have a line after which I want to perform my INSERT.
eg:
File Before INSERT:
...
FROM LOCAL :LOAD_FILE
REJECTED DATA :REJECT_PATH
...
File After INSERT:
...
FROM LOCAL :LOAD_FILE
DELIMITER AS '|'
REJECTED DATA :REJECT_PATH
...
I've tried writing down many SED commands but they are generating errors. One of them is:
sed 'LOAD_FILE/a/ DELIMITER AS \'\|\'/g' SOURCE > DESTINATION
awk -v line='DELIMITER AS '"'|'"'' '1; /LOAD_FILE/{print line }' input
FROM LOCAL :LOAD_FILE
DELIMITER AS '|'
REJECTED DATA :REJECT_PATH
Using surrounding double quotes:
sed "/FROM LOCAL :LOAD_FILE/s//&\nDELIMITER AS '|'/" file
or single quotes (safer to avoid unwanted variable expansion):
sed '/FROM LOCAL :LOAD_FILE/s//&\nDELIMITER AS '"'|'"'/' file
This might work for you (GNU sed):
sed '/LOAD_FILE/aDELIMITER AS '\'\|\' file
This appends the line DELIMITER AS \'\|\' following the match on LOAD_FILE
N.B. The sed command is in two parts, the /LOAD_FILE/aDELIMITER AS is concatenated with \'\|\'
If you prefer:
sed 's/LOAD_FILE/&\nDELIMITER AS '\'\|\''/' file
Another way of putting it :
sed -e ':a;N;$!ba;s/LOAD_FILE\n/LOAD_FILE\nDELIMITER AS \x27|\x27\n/g'
about syntax I used :
How can I replace a newline (\n) using sed?

sed is replacing matched text with output of another command, but that command's output contains expansion characters [duplicate]

This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 6 years ago.
I'm trying to replace text in a file with the output of another command. Unfortunately, the outputted text contains characters bash expands. For example, I'm running the following script to change the file (somestring references output that would break the sed command):
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
sed '0,/^title/s/^title*/'"$somestring"'\n&/' $HOME/example.txt
sed fails with this error:
sed: -e expression #1, char 30: unknown option to `s'
I think bash is substuting the contents of $somestring when building the sed command, but is then trying to expand the resulting text. I can't put the entire sed script in single quotes, I need bash to expand it the first time, just not the second. Any suggestions? Thanks
here the forward slash / is the problem. If it's the only issue you can set sed to use a different delimiter.
for example
$ somestring="abc/def"; echo xxx | sed 's/xxx/'"$somestring"'/'
sed: -e expression #1, char 11: unknown option to `s'
$ somestring="abc/def"; echo xxx | sed 's_xxx_'"$somestring"'_'
abc/def
you also need to worry about & and \ chars and escape them if can appear in the replacement text.
If you can't control the the replacement string, either you have to sanitize with another sed script or, alternatively use r command to read it from a file. For example,
$ seq 5 | sed -e '/3/{r replace' -e 'd}'
1
2
3slashes///1ampersand&and2backslashes\\end
4
5
where
$ cat replace
3slashes///1ampersand&and2backslashes\\end
You have several errors here:
the string somestring has characters that are significative for sed command (the most important being '/' that you are using as a delimiter) You can escape it, by substituting it with a previous
somestring=$(echo "$somestring" | sed -e 's/\//\\\//g')
that will convert your / chars to \/ sequences.
you are using sed '0,/^title/s/^title*/'"$somestring"'\n&/' $HOME/example.txt which is looking to substitute the string titl followed by any number of e characters by that $somestring value, followed by a new line and the original one. Unfortunately, sed(1) doesn't allow you to use newline characters in the pattern substitution side of the s command, but you can afford the result by using the i command with a text consisting of you pattern (preceding any new line by a \ to interpret it as literal):
Finally the script leads to:
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
somestring=$(echo "$somestring" | sed -e 's/\//\\\//g')
sed '/^title/i\
'"$somestring\\
" $HOME/example.txt
If your shell is Bash, you can use parameter substitution to replace the problematic /:
somestring="{somestring//\//\\/}"
That looks scary, but is easier to understand if you look at the version that replaces x with __:
somestring="${somestring//x/__}"
It might be easier to use (say) underscore as the delimiter for your sed s command, and then the substitution above would be
somestring="${somestring//_/\\_}"
If you already have backslashes, you'll need to first replace those:
somestring="${somestring//\\/\\\\}"
somestring="{somestring//\//\\/}"
If there were other characters that needed escaping (e.g. on the search side of s///), then you could extend the above appropriately.
This URL provides the cleanest answer:
Command to escape a string in bash
printf "%q" "$someVariable"
will escape any characters you need escaped for you.

How to stop newline chars from escaping OLD gnu sed command

I am trying to replace a line in a file with multiple lines. When I had only one new line char ( \'$'\n ). it worked fine, however when I use two of them, it escapes my sed and the file wont run anymore.
sed 's/TextImLookingFor/My\'$'\nReplacement\'$'\nText/g' /path/to/File.txt
File.txt:
This is a file
TextImLookingFor
look at all this text
DesiredOutput
This is a file
My
Replacement
Text
look at all this text
Actual Output
unexpected EOF while looking for matching ''''
syntax error: unexpected end of file
Using older BSD sed you can do:
sed $'s/TextImLookingFor/My\\\nReplacement\\\nText/' file
This is a file
My
Replacement
Text
look at all this text
This should work with newer gnu-sed as well. However newer gnu-sed may just need:
sed 's/TextImLookingFor/My\nReplacement\nText/' file
This might work for you (GNU sed):
sed '/TextImLookingFor/c\My\nReplacement\nText' file
The problem with this command
sed 's/TextImLookingFor/My\'$'\nReplacement\'$'\nText/g' /path/to/File.txt
is that it isn't parsing the way you expect it is.
You cannot escape a single quote inside a single quoted string. You can escape a single quote inside a $'...' quoted string however (I'm not really sure why).
So the above command does not parse this way (as you might expect):
[sed] [s/TextImLookingFor/My\'$[\nReplacement\'$]\nText/g] [/path/to/File.txt]
instead it parses this way:
[sed] [s/TextImLookingFor/My\]$[\nReplacement\'$]\nText/g' [/path/to/File.txt]
with a mismatched single quote at the end and an unquoted \nText/g bit.
That is the cause of your problem.
If you can't just use \n in your replacement (your version of sed doesn't support that) and you need to use $'\n' then you would need to use something like
sed 's/TextImLookingFor/My\'$'\nReplacement\\'$'\nText/g' /path/to/File.txt

search and replace string using sed

i have a sed command like this for search and replace string inside a file:
sed -i -e 's/`db1`./`db2`./g' result/files1.sql
that is working fine to replace the db1 to db2 inside the file of: result/files1.sql
however when i change it to bash and variable format, it does not work.
sed -i -e "s/`${mydbname}`./`${mydbname2}`./g" "${mypath}"
i get error like:
./mycoolscript: line 241: db1: command not found
./mycoolscript: line 241: db2: command not found
any solution would be great.
If is something you need to replace, you will need to escape by . Here it is
sed -i -e "s/\`${mydbname}\`./\`${mydbname2}\`./g" "${mypath}"
Escape the backtick character
sed -i -e "s/\`${mydbname}\`./\`${mydbname2}\`./g" "${mypath}"
Bash treats the part within backticks as a command and first executes that.
Try this
sed -i -e "s/${mydbname}/${mydbname2}/g" "${mypath}"
There is one more way, of using single quotes for literals & double quotes only around variables/escape sequences.
sed -i -e 's/`'"${mydbname}"'`./`'"${mydbname2}"'`./g' "${mypath}"
Because of single quotes, you will not have to escape the special characters.
The trade-off between escaping special characters vs. using mix of single & double quotes would depend on number of special characters vs. number of variables.
If there are too many characters that would need escaping & less number of variables, I would prefer mix of single & double quotes.

Resources