replacement with sed linux - linux

I need to perform a replacement with sed in linux but it doesn't work.
from [$sonarqubeName] to [$projectName][$branchName]
I tried sed -i 's/[$projectName]/[$projectName][$branchName]/g'
sed -i 's/[$projectName]/[$projectName][$branchName]/g'

The characters [, $, ] have special meaning inside the regular expressions (and some other characters as well, but they are not appearing in your search string). To use them as literal symbols you need to escape them with a backslash in the search expression. Try
sed -i 's/\[\$sonarqubeName\]/[$projectName][$branchName]/g'

Related

sed doesn't replace variable

I'm trying to replace some regex line in a apache file.
i define:
OLD1="[0-9]*.[0-9]+"
NEW1="[a-z]*.[0-9]"
when i'm executing:
sed -i 's/$OLD1/$NEW1/g' demo.conf
there's no change.
This is what i tried to do
sed -i "s/${OLD1}/${NEW1}/g" 001-kms.conf
sed -i "s/"$OLD1"/"$NEW1"/g" 001-kms.conf
sed -i "s~${OLD1}~${NEW1}~g" 001-kms.conf
i'm expecting that the new file will replace $OLD1 with $NEW1
OLD1="[0-9]*.[0-9]+"
Because the [ * . are all characters with special meaning in sed, we need to escape them. For such simple case something like this could work:
OLD2=$(<<<"$OLD1" sed 's/[][\*\.]/\\&/g')
It will set OLD2 to \[0-9\]\*\.\[0-9\]+. Note that it doesn't handle all the possible cases, like OLD1='\.\[' will convert to OLD2='\\.\\[ which means something different. Implementing a proper regex to properly escape, well, other regex I leave as an exercise to others.
Now you can:
sed "s/$OLD2/$NEW1/g"
Tested with:
OLD1="[0-9]*.[0-9]+"
NEW1="[a-z]*.[0-9]"
sed "s/$(sed 's/[][\*\.]/\\&/g' <<<"$OLD1")/$NEW1/g" <<<'XYZ="[0-9]*.[0-9]+"'
will output:
XYZ="[a-z]*.[0-9]"
you need matching on exact string
You would need something that can match on exact string [0-9]*.[0-9]+ which sed does not support well.
Therefore instead I am using this pipeline replacing one character at a time (it also is easier to read I think):echo "[0-9]*.[0-9]+" | sed 's/0/a/' | sed 's/9/z/' | sed 's/+//'
You would have to cat your files or use find with execute to then apply this pipe.
I had tried following (from other SO answers):
- sed 's/\<exact_string/>/replacement/'doesn't work as \< and \> are left and right word boundaries respectively.
- sed 's/(CB)?exact_string/replacement/'found in one answer but nowhere in documentation
I used Win 10 bash, git bash, and online Linux tools with the same results.
when I thought matching was on the pattern rather than exact string
Replacement cannot be a regex - at most it can reference parts of the regex expression which matched. From man sed:
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
Additionally you have to escape some characters in your regex (specifically . and +) unless you add option -E for extended regex as per comment under your question. (N.B. only if you want to match on the full-stop . rather than it meaning any character)
$ echo "01.234--ZZZ" | sed 's/[0-9]*\.[0-9]\+/REPLACEMENT/g'
REPLACEMENT--ZZZ

sed help: matching and replacing a literal "\n" (not the newline)

i have a file which contains several instances of \n.
i would like to replace them with actual newlines, but sed doesn't recognize the \n.
i tried
sed -r -e 's/\n/\n/'
sed -r -e 's/\\n/\n/'
sed -r -e 's/[\n]/\n/'
and many other ways of escaping it.
is sed able to recognize a literal \n? if so, how?
is there another program that can read the file interpreting the \n's as real newlines?
Can you please try this
sed -i 's/\\n/\n/g' input_filename
What exactly works depends on your sed implementation. This is poorly specified in POSIX so you see all kinds of behaviors.
The -r option is also not part of the POSIX standard; but your script doesn't use any of the -r features, so let's just take it out. (For what it's worth, it changes the regex dialect supported in the match expression from POSIX "basic" to "extended" regular expressions; some sed variants have an -E option which does the same thing. In brief, things like capturing parentheses and repeating braces are "extended" features.)
On BSD platforms (including MacOS), you will generally want to backslash the literal newline, like this:
sed 's/\\n/\
/g' file
On some other systems, like Linux (also depending on the precise sed version installed -- some distros use GNU sed, others favor something more traditional, still others let you choose) you might be able to use a literal \n in the replacement string to represent an actual newline character; but again, this is nonstandard and thus not portable.
If you need a properly portable solution, probably go with Awk or (gasp) Perl.
perl -pe 's/\\n/\n/g' file
In case you don't have access to the manuals, the /g flag says to replace every occurrence on a line; the default behavior of the s/// command is to only replace the first match on every line.
awk seems to handle this fine:
echo "test \n more data" | awk '{sub(/\\n/,"**")}1'
test ** more data
Here you need to escape the \ using \\
$ echo "\n" | sed -e 's/[\\][n]/hello/'
sed works one line at a time, so no \n on 1 line only (it's removed by sed at read time into buffer). You should use N, n or H,h to fill the buffer with more than one line, and then \n appears inside. Be careful, ^ and $ are no more end of line but end of string/buffer because of the \n inside.
\n is recognized in the search pattern, not in the replace pattern. Two ways for using it (sample):
sed s/\(\n\)bla/\1blabla\1/
sed s/\nbla/\
blabla\
/
The first uses a \n already inside as back reference (shorter code in replace pattern);
the second use a real newline.
So basically
sed "N
$ s/\(\n\)/\1/g
"
works (but is a bit useless). I imagine that s/\(\n\)\n/\1/g is more like what you want.

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.

Why i need to escape () sometimes in sed

When i use sed and use braces like this
sed -re 's/top([0-9]+)//g'
I works for this but i have seen sometimes i need to escape the braces and sometimes it works without escaping. why is that
Why does \w don't work with awk
This depends on the -r switch you are using:
-r, --regexp-extended
use extended regular expressions in the script.
With -r the brackets mean a captured group, and to match literal brackets you have to escape them.
Without -r it's vice versa.
Consider:
$ sed -r 's/foo([0-9]*)/\1/' <<<'foo123'
123
$ sed 's/foo([0-9]*)/\1/' <<<'foo123'
sed: -e expression #1, char 17: invalid reference \1 on `s' command's RHS
$ sed 's/([0-9]*)//' <<<'foo(123)'
foo
$ sed 's/foo\([0-9]*\)/\1/' <<<'foo(123)'
(123)
(in the last one the groups matches zero digits)
In the classical regular expressions sed uses, you have to backslash the parentheses to give them the special meaning. If your sed supports -r, it can use "extended" regular expressions, where parentheses have the special meaning without backslashes, backslashing them makes them lose the meaning.
\w should work in awk. What have you tried, what output did you expect and what output did you get?

replace old-link-url to new-link-url with sed

I'm writing a script in bash that would replace old-link-url to new-link-url
my problem is that sed can't replace the url because of the slashes. If i put just some text it works.
my code
sed -e s/"$old_link"/"$new_link"/g wget2.html > playlist.txt
sed supports any character as separator, so if the pattern you are trying to replace contains /, use a different separator. Most commonly used are # and |
sed 's|foo|bar|g' input
sed 's#foo#bar#g' input
Don't forget to put double quotes if you are using variables in sed substitution. Also, if your variable have / then use a different delimiter for sed. You can use _, %, |, # and many more.
So may be something like this would work -
sed -e "s_"$old_link"_"$new_link"_g" wget2.html > playlist.txt

Resources