Remove substring matching pattern both in the beginning and the end of the variable

42,166

Solution 1

Well, you can't nest ${var%}/${var#} operations, so you'll have to use temporary variable.

Like here:

var="http://whatever/score/"
temp_var="${var#http://}"
echo "${temp_var%/score/}"

Alternatively, you can use regular expressions with (for example) sed:

some_variable="$( echo "$var" | sed -e 's#^http://##; s#/score/$##' )"

Solution 2

$ var='https://www.google.com/keep/score'
$ var=${var#*//} #removes stuff upto // from begining
$ var=${var%/*} #removes stuff from / all the way to end
$ echo $var
www.google.com/keep

Solution 3

You have to do it in 2 steps :

$ string="fooSTUFFfoo"
$ string="${string%foo}"
$ string="${string#foo}"
$ echo "$string"
STUFF

Solution 4

There IS a way to do it one step using only built-in bash functionality (no running external programs such as sed) -- with BASH_REMATCH:

url=http://whatever/score/
re='https?://(.*)/score/'
[[ $url =~ $re ]] && printf '%s\n' "${BASH_REMATCH[1]}"

This matches against the regular expression on the right-hand side of the =~ test, and puts the groups into the BASH_REMATCH array.


That said, it's more conventional to use two PE expressions and a temporary variable:

shopt -s extglob
url=http://whatever/score/
val=${url#http?(s)://}; val=${val%/score/}
printf '%s\n' "$val"

...in the above example, the extglob option is used to allow the shell to recognized "extglobs" -- bash's extensions to glob syntax (making glob-style patterns similar in power to regular expressions), among which ?(foo) means that foo is optional.


By the way, I'm using printf rather than echo in these examples because many of echo's behaviors are implementation-defined -- for instance, consider the case where the variable's contents are -e or -n.

Share:
42,166

Related videos on Youtube

bobylapointe
Author by

bobylapointe

Updated on February 09, 2020

Comments

  • bobylapointe
    bobylapointe about 4 years

    As the title says, I'm looking for a way to remove a defined pattern both at the beginning of a variable and at the end. I know I have to use # and % but I don't know the correct syntax.

    In this case, I want to remove http:// at the beginning, and /score/ at the end of the variable $line which is read from file.txt.

    • Admin
      Admin almost 11 years
      What kind of pattern? Can you be a bit more specific?
    • bobylapointe
      bobylapointe almost 11 years
      yes, in this case: http:// at the beginning, and /score/ at the end. The $line is read from a file.txt
    • doubleDown
      doubleDown almost 11 years
      What you are looking for is parameter expansion, specifically to your case the ${parameter#word} and ${parameter%word} near the end of this section of Bash manual
  • bobylapointe
    bobylapointe almost 11 years
    I'm way more familiar with regular expressions. This is interesting. I know sed a bit. The question is, how to use the output produced by sed to use it in another command. Let's say to start a script. ./script.sh $variablemodifiedbysed
  • Admin
    Admin almost 11 years
    Updated the answer to show that the output of sed can be stored in variable, for reuse.
  • bobylapointe
    bobylapointe almost 11 years
    This finally works like a charm. I've been spending two hours figuring this out. I'm sure the others work as well, but again, I like using regular expressions. Thanks man !
  • jaypal singh
    jaypal singh almost 11 years
    @bobylapointe Don't forget to mark this answer by clicking the check mark. :)
  • Charles Duffy
    Charles Duffy almost 11 years
    Why use sed when bash has regular expression matching built-in?
  • Nazar
    Nazar about 7 years
    In my case, the string may or may not start with 'boo' or 'foo' and if it starts with any of them how could I implement an OR into the parsing to remove "boo" OR "foo" from beginning of a string?
  • axolotl
    axolotl over 2 years
    what are these called and how do I learn more about such hacks in bash string manip?