Question Detail
I am trying to replace part of the string, but can not find a proper regex for sed to execute it properly.
I have a string
/abc/foo/../bar
And I would like to achive the following result:
/abc/bar
I have tried to do it using this command:
echo $string | sed 's/\/[^:-]*\..\//\//'
But as result I am getting just /bar
.
I understand that I must use group, but I just do not get it.
Could you, please, help me to find out this group that could be used?
Question Answer
You can use
#!/bin/bash
string='/abc/foo/../bar'
sed -nE 's~^(/[^/]*)(/.*)?/\.\.(/[^/]*).*~\1\3~p' <<< "$string"
See the online demo. Details:
-n
– suppresses default line output
E
– enables POSIX ERE regex syntax
^
– start of string
(/[^/]*)
– Group 1: a /
and then zero or more chars other than /
(/.*)?
– an optional group 2: a /
and then any text
/\.\.
– a /..
fixed string
(/[^/]*)
– Group 3: a /
and then zero or more chars other than /
.*
– the rest of the string.
\1\3
replaces the match with Group 1 and 3 values concatenated
p
only prints the result of successful substitution.
You can use a capture group for the first part and then match until the last /
to remove.
As you are using /
to match in the pattern, you can opt for a different delimiter.
#!/bin/bash
string="/abc/foo/../bar"
sed 's~\(/[^/]*/\)[^:-]*/~\1~' <<< "$string"
The pattern in parts:
\(
Capture group 1
/[^/]*/
Match from the first till the second /
with any char other than /
in between
\)
Close group 1
[^:-]*/
Match optional chars other than :
and -
then match /
Output
/abc/bar
Using sed
$ sed 's#^\(/[^/]*\)/.*\(/\)#\1\2#' input_file
/abc/bar
or
$ sed 's#[^/]*/[^/]*/##2' input_file
/abc/bar
Using awk
string='/abc/foo/../bar'
awk -F/ '{print "/"$2"/"$NF}' <<< "$string"
#or
awk -F/ 'BEGIN{OFS=FS}{print $1,$2,$NF}' <<< "$string"
/abc/bar
Using bash
string='/abc/foo/../bar'
echo "${string%%/${string#*/*/}}/${string##*/}"
/abc/bar
Using any sed:
$ echo "$string" | sed 's:\(/[^/]*/\).*/:\1:'
/abc/bar