Home > Enterprise >  Sed: can not replace part of the string whithout replacing all of it
Sed: can not replace part of the string whithout replacing all of it

Time:04-12

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?

CodePudding user response:

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.

CodePudding user response:

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

CodePudding user response:

Using sed

$ sed 's#^\(/[^/]*\)/.*\(/\)#\1\2#' input_file
/abc/bar

or

$ sed 's#[^/]*/[^/]*/##2' input_file
/abc/bar

CodePudding user response:

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
  • Related