Regex matching using SED in bash - regex

I want to match the following line with the regex in sed:
db=connect_str=DBI:SQLAnywhere:ENG=ABC1_hostname12;DBN=ABC12;UID=USERID;PWD=passwd123;LINKS=tcpip{host=10.11.12.13:1234}
The regex I am using is:
sed -n '/ABC1_.+;/p' Config/db_conn.cfg
but this does not work. On the other hand, it works if I use:
sed -n '/ABC1_.*;/p' Config/db_conn.cfg
Can someone please explain why it's not working? Also is there another way to match it?

It's because sed is basic regex by default, which needs + to be escaped or else it represents a literal + instead of a regex +:
sed -n '/ABC1_.\+;/p' Config/db_conn.cfg
To use regex you're familiar with try sed -r -n (extended regex) and then you can do:
sed -r -n '/ABC1_.+;/p' Config/db_conn.cfg

Related

Regex - sed to extract word between patterns

I'm trying to extract the word hello from ENC(hello) using sed.
I've tried the following but so far no joy:
property="ENC(hello)" && echo "$property" | sed 's/(?<=^ENC\()(.*)(?=\))/\1/'
Can you advise what am doing wrong?
property="ENC(hello)" && echo "$property" | sed -e 's/ENC(\(.*\))/\1/'
the problem is that sed seems to not support the "lazy" match but to be always greedy, so if in one line you have
ENC(hello) ENC(world)
such regex won't help

BASH: replacing PERL with SED for in-place substitution

Would like to replace this statement with perl:
perl -pe "s|(?<=://).+?(?=/)|$2:80|"
with
sed -e "s|<regex>|$2:80|"
Since sed has a much less powerful regex engine (for example it does not support look-arounds) the task boils down to writing a sed compatible regex to match only a domain name in a fully qualitied URL. Examples:
http://php2-mindaugasb.c9.io/Testing/JS/displayName.js
http://php2-mindaugasb.c9.io?a=Testing.js
http://www.google.com?a=Testing.js
Should become:
http://$2:80/Testing/JS/displayName.js
http://$2:80?a=Testing.js
http://$2:80?a=Testing.js
A solution like this would be ok:
sed -e "s|<regex>|http://$2:80|"
Thanks :)
Use the below sed command.
$ sed "s~//[^/?]\+\([?/]\)~//\$2:80\1~g" file
http://$2:80/Testing/JS/displayName.js
http://$2:80?a=Testing.js
http://$2:80?a=Testing.js
You must need to escape the $ at the replacement part.
sed 's|http://[^/?]*|http://$2:80|' file
Output:
http://$2:80/Testing/JS/displayName.js
http://$2:80?a=Testing.js
http://$2:80?a=Testing.js

Using sed to replace IP using regex

Assuming a simple text file:
123.123.123.123
I would like to replace the IP inside of it with 222.222.222.222. I have tried the below but nothing changes, however the same regex seems to work in this Regexr
sed -i '' 's/(\d{1,3}\.){3}\d{1,3}/222.222.222.222/' file.txt
Am I missing something?
Two problems here:
sed doesn't like PCRE digit property \d, use range: [0-9] or POSIX [[:digit:]]
You need to use -r flag for extended regex as well.
This should work:
s='123.123.123.123'
sed -r 's/([0-9]{1,3}\.){3}[0-9]{1,3}/222.222.222.222/' <<< "$s"
222.222.222.222
Better would be to use anchors to avoid matching unexpected input:
sed -r 's/^([0-9]{1,3}\.){3}[0-9]{1,3}$/222.222.222.222/' <<< "$s"
PS: On OSX use -E instead of -r:
sed -E 's/^([0-9]{1,3}\.){3}[0-9]{1,3}$/222.222.222.222/' <<< "$s"
222.222.222.222
You'd better use -r, as indicated by anubhava.
But in case you don't have it, you have to escape every single (, ), { and }. And also, use [0-9] instead of \d:
$ sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/222.222.222.222/' <<< "123.123.123.123"
222.222.222.222

How to extract substring with sed but first occurence only?

Using sed -n "s/.*\(\/.*\/\).*/\1/p on /string1/string2 produces string1, as expected.
However, using the same on /string1/string2/string3 produces string2.
How can I print the first occurrence only, that is string1.
This does exactly what I wanted:
sed -n "s/[^/]*\(\/[a-z]*\).*/\1/p"
You can use this sed:
sed -n 's|/\([^/]*\)/.*|\1|p'
Avoid escaping / by using an alternate delimiter.
This might work for you (GNU sed):
sed -n 's/[^\/]*\(\/[^\/]*\/\).*/\1/p' file
perl's non-greedy regex quantifiers are handy:
perl -pe 's{.*?(/.*?/).*}{$1}' <<END
foobar/string1/string2/string3
END
/string1/
If you want to use bash shell:
str="foobar/string1/string2/string3"
string1=$( IFS=/; set -- $str; echo $2 )

sed plus sign doesn't work

I'm trying to replace /./ or /././ or /./././ to / only in bash script. I've managed to create regex for sed but it doesn't work.
variable="something/./././"
variable=$(echo $variable | sed "s/\/(\.\/)+/\//g")
echo $variable # this should output "something/"
When I tried to replace only /./ substring it worked with regex in sed \/\.\/. Does sed regex requires more flags to use multiplication of substring with + or *?
Use -r option to make sed to use extended regular expression:
$ variable="something/./././"
$ echo $variable | sed -r "s/\/(\.\/)+/\//g"
something/
Any sed:
sed 's|/\(\./\)\{1,\}|/|g'
But a + or \{1,\} would not even be required in this case, a * would do nicely, so
sed 's|/\(\./\)*|/|g'
should suffice
Two things to make it simple:
$ variable="something/./././"
$ sed -r 's#(\./){1,}##' <<< "$variable"
something/
Use {1,} to indicate one or more patterns. You won't need g with this.
Use different delimiterers # in above case to make it readable
+ is ERE so you need to enable -E or -r option to use it
You can also do this with bash's built-in parameter substitution. This doesn't require sed, which doesn't accept -r on a Mac under OS X:
variable="something/./././"
a=${variable/\/*/}/ # Remove slash and everything after it, then re-apply slash afterwards
echo $a
something/
See here for explanation and other examples.