32

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.

codeforester
  • 39,467
  • 16
  • 112
  • 140
bobylapointe
  • 663
  • 1
  • 5
  • 12
  • What kind of pattern? Can you be a bit more specific? –  Jun 16 '13 at 00:03
  • yes, in this case: http:// at the beginning, and /score/ at the end. The $line is read from a file.txt – bobylapointe Jun 16 '13 at 00:04
  • 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](http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) – doubleDown Jun 16 '13 at 03:58

5 Answers5

34

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/$##' )"
chepner
  • 497,756
  • 71
  • 530
  • 681
  • 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 – bobylapointe Jun 16 '13 at 00:15
  • 2
    Updated the answer to show that the output of sed can be stored in variable, for reuse. –  Jun 16 '13 at 00:28
  • 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 ! – bobylapointe Jun 16 '13 at 00:35
  • Why use sed when bash has regular expression matching built-in? – Charles Duffy Jun 16 '13 at 04:20
  • what are these called and how do I learn more about such hacks in bash string manip? – axolotl Sep 28 '21 at 23:26
15
$ 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
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • Use more "quotes" > "Double quote" every literal that contains spaces/metacharacters and _every_ expansion: `"$var"`, `"$(command "$var")"`, `"${array[@]}"`, `"a & b"`. Use `'single quotes'` for code or literal `$'s: 'Costs $5 US'`, `ssh host 'echo "$HOSTNAME"'`. See [when-is-double-quoting-necessary](https://unix.stackexchange.com/questions/68694/when-is-double-quoting-necessary) – Gilles Quénot Mar 10 '23 at 18:49
5

You have to do it in 2 steps :

$ string="fooSTUFFfoo"
$ string="${string%foo}"
$ string="${string#foo}"
$ echo "$string"
STUFF
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • 1
    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? – Nazar Feb 16 '17 at 14:34
3

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.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
0

how about

export x='https://www.google.com/keep/score';
var=$(perl -e 'if ( $ENV{x} =~ /(https:\/\/)(.+)(\/score)/ ) { print qq($2);}')
michael501
  • 1,452
  • 9
  • 18