How to replace a string with string containing multiple / characters - bash

I am trying to change the following string
FROM java_jre_8#sha256:92f22331226b9b3c43a15eeeb304dd7
to
FROM docker-registry.service.consul:5000/java_jre_8#sha256:92f22331226b9b3c43a15eeeb304dd7
but am having difficult with sed as a result of / character
This is for a build server.

There are two ways of doing this. The first is to escape each / in the string you're replacing:
sed 's/from/to with \/ ... /'
The other, more simple way is to use a delimiter other than /. While most sed examples use / as a delimiter, you can use any character:
sed 's|from|to with / ...|'
Here, the | is the first character following s, and therefore sed knows to use this as a delimiter.

You can use # as the delimiter as it doesn't appear in your string (you can still use / but then you'll have to quote the actual /s that are part of the string).
sed "s#FROM java_jre_8##FROM docker-registry.service.consul:5000/java_jre_8##'
Example:
$ echo "FROM java_jre_8#sha256:92f22331226b9b3c43a15eeeb304dd7" | sed "s#FROM java_jre_8##FROM docker-registry.service.consul:5000/java_jre_8##"
FROM docker-registry.service.consul:5000/java_jre_8#sha256:92f22331226b9b3c43a15eeeb304dd7

Related

How to Search for a String and replace the n to n+10 character from that string with another 10 character in Unix

I want to search for a string and then from that string i want to replace 10 characters with another 10 characters.
For Example,
/prd/edm/hadoop/ifrs/eglex/hdata/ifrs_sri_open/eglex_*_txnacbal/ods=2020_02_23/
i want to search for string "ods=" and replace "2020_02_23" with "2020_02_30"
Since that date "2020_02_23" is not consistent i wanted to search with "ods=" which is static and one time for a line.
Like this more lines are there in the file.
I tried:
cat dta_1.sh | sed 's/.*ods=//' | cut -c1-10
I want to search for string "ods=" and replace "2020_02_23" with
"2020_02_30"
sed 's|\(.*ods=\).*|\12020_02_30/|g' inputfile
The regex inside the parenthesis \( \) is reproduced by \1, and the string after ods= is replaced by 2020_02_30/.
If there could be something else besides / after the date, then go for this:
sed 's|\(.*ods=\)...._.._..|\12020_02_30|g' inputfile
I've completed this using the below,
sed -i '/ods=/ s|ods="[^"]*"|ods='"${DATE_FORMAT2}"'|g' dta_2.sh
Thanks all for the response

tr command: strange behavior with | and \

Let's say I have a file test.txt with contents:
+-foo.bar:2.4
| bar.foo:1.1:test
\| hello.goobye:3.3.3
\|+- baz.yeah:4
I want to use the tr command to delete all instances of the following set of characters:
{' ', '+', '-', '|', '\'}
Done some pretty extensive research on this but found no clear/concise answers.
This is the command that works:
input:
cat test.txt | tr -d "[:blank:]|\\\+-"
output:
foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4
I experimented with many combinations of that set and I found out that the '-' was being treated as a range indicator (like... [a-z]) and therefore must be put at the end. But I have two main questions:
1) Why must the backslash be double escaped in order to be included in the set?
2) Why does putting the '|' at the end of the set string cause the tr program to delete everything in the file except for trailing new line characters?
Like this:
tr -d '\-|\\+[:blank:] ' < file
You have to escape the - because it is used for denoting ranges of characters like:
tr -d '1-5'
and must therefore being escaped if you mean a literal hyphen. You can also put it at the end. (learned that, thanks! :) )
Furthermore the \ must be escaped when you mean a literal \ because it has a special meaning needed for escape sequences.
The remaining characters must not being escaped.
Why must the \ being doubly escaped in your example?
It's because you are using a "" (double quoted) string to quote the char set. A double quoted string will be interpreted by the shell, a \\ in a double quoted string means a literal \. Try:
echo "\+"
echo "\\+"
echo "\\\+"
To avoid to doubly escape the \ you can just use single quotes as in my example above.
Why does putting the '|' at the end of the set string cause the tr program to delete everything in the file except for trailing new line characters?
Following CharlesDuffy's comment having the | at the end means also that you had the unescaped - not at the end, which means it was describing a range of characters where the actual range depends on the position you had it in the set.
another approach is to define the allowed chars
$ tr -cd '[:alnum:]:.\n' <file
foo.bar:2.4
bar.foo:1.1:test
hello.goobye:3.3.3
baz.yeah:4
or, perhaps delete all the prefix non-word chars
$ sed -E 's/\W+//' file

Adding zero to part of string using sed

I have SNMP outputs like:
IP-MIB::ipNetToMediaPhysAddress.5122.192.19.3.25 = STRING: 34:8:4:56:f4:70
As you can see mac-address output is incorrect, and i fix it with sed:
echo IP-MIB::ipNetToMediaPhysAddress.5122.192.19.3.25 = STRING: 34:8:4:56:f4:70 |
sed -e 's/\b\(\w\)\b/0\1/g'
Output:
IP-MIB::ipNetToMediaPhysAddress.5122.192.19.03.25 = STRING: 34:08:04:56:f4:70
It fixes address but changes IP as well from 192.19.3.25 to 192.19.03.25. How can I avoid it and force to perform sed only after STRING: or only after last space in the string ?
The MAC address is colon-separated. You can use that to limit the substitutions. This will perform the substitutions that you are interested in but only if the word character is next to a colon:
sed -e 's/\b\w:/0&/g; s/:\(\w\)\b/:0\1/g'
For example:
$ echo IP-MIB::ipNetToMediaPhysAddress.5122.192.19.3.25 = STRING: 34:8:4:56:f4:70 | sed -e 's/\b\w:/0&/g; s/:\(\w\)\b/:0\1/g'
IP-MIB::ipNetToMediaPhysAddress.5122.192.19.3.25 = STRING: 34:08:04:56:f4:70
How it works
s/\b\w:/0&/g
This performs the substitution if the word character is preceded by a word break, \b, and followed by a colon. Since we just need to put a zero in front of the entire matched text, not just some section of it, we can omit the parens and just use & to copy the matched text.
s/:\(\w\)\b/:0\1/g
If there are any remaining substitutions that need to be done where the word character is preceded by a colon and followed by a word break, this does them.
Note: We are using GNU extensions that may not be portable.
Another way with sed if the MAC address is at end of line
echo IP-MIB::ipNetToMediaPhysAddress.5122.192.19.3.25 = STRING: 4:8:d:56:f4:7 |
sed -E '
s/$/:/
:A
s/([^[:xdigit:]])([[:xdigit:]]:)/\10\2/
tA
s/:$//'

How to replace all underscores in a text except the ones that are part of a specific word or pattern in Unix Shell

I have a file that contains lot of underscores and i have to replace all of them with empty string except the ones that are part of a specific string usr_mstr.
I have tried sed command, it replaces underscore and excludes the words i provided, but it also replaces the character immediately following underscore! Any help will greatly be appreciated..
echo "fname_sname_id_usr_mstr" | sed 's/_[^usr_mstr]//g'
Expected output:
fnamesnameidusr_mstr
Actual Output:
fnamenamedusr_mstr
(s and i got replaced)
This might work for you (GNU sed):
sed -r 's/(usr_mstr)|_/\1/g' file
Globally replace usr_mstr by itsself or replace _ by nothing
[^usr_mstr] is a character class that matches any character that's not u, s, r, m, t, or _.
Perl supports "look-around" assertions, so you can write:
echo "fname_sname_id_usr_mstr_x_usr_other_mstr_y_usrmstr_z" \
| perl -pe 's/(?<!usr)_//g;s/_(?!mstr)//g'
i.e. replace _ if not preceded by usr, and not followed by mstr.
You cannot solve this with standard sed BRE regex alone. With sed you would basically need to replace "usr_mstr" with a placeholder string, then replace all the underscores and then replace the placeholder string with the "usr_master" ..
echo "fname_sname_id_usr_mstr" |
{ null="###"; sed "s/usr_mstr/$null/g; s/_//g; s/$null/usr_mstr/g" ;}
An alternative is to try awk :
echo "fname_sname_id_usr_mstr" |
awk -v s="usr_mstr" 'BEGIN{FS=OFS=s} {for(i=1; i<=NF; i++) gsub("_","",$i)}1'
Which should work as long a s does not contains regular characters that are special in extended regular expressions.

sed command replacing string that contains special character is not working

i want to replace a special string inside a file.txt. my strings are like this :
-> Old String
tech=/lsf/dfg/a.v,/ldf/fgh/b.v
-> New String
tech=$var
i have tried following
sed -i 's/tech=/lsf/dfg/a.v,/ldf/fgh/b.v/tech=$var/g' file.txt
it doesnt work.
sed -i 's#tech=/lsf/dfg/a.v,/ldf/fgh/b.v#tech=$var#g' file.txt
Just replace the delimiters '/' for the sed expression with '#' (or another character that is not in the string you are trying to match and replace).

Resources