18

Bash 4.2 added support for negative substring lengths:

http://tldp.org/LDP/abs/html/abs-guide.html#SUBSTREXTR01

Example 37-12. Negative parameter in string-extraction construct

When the "length" parameter is negative, it serves as an offset-from-end parameter.

For example, the following outputs "World" when tested on Ubuntu:

STR="Hello World!"
echo ${STR:6:-1}

But in OS X (GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)), that usage produces the following error:

-1: substring expression < 0

Is this OS X specific, or was it disabled again in later bash updates? Is there a way to enable this functionality for OS X?

4 Answers4

12

While flabdablet's solution only works for fixed length strings you can use this as a drop-in replacement for dynamically sized strings:

echo ${STR:6:$((${#STR} - 6 - 1))}

In detail:

  • ${#STR} returns the length of the string.
  • $((a - b - c)) does mathematical subtraction
  • ${STR:start:len} returns a substring.

So combined the second argument to the substring expression is the length of the string minus the starting offset minus the value you would specify as negative value in the newer bash syntax.

kayahr
  • 243
3

It is possible to cut at the end dynamically by using the length as input to calculate.

${STR:0:${#STR}-2}

The -2 is the negative amount.

2

${STR:6:${#STR}-7} should be a working drop-in replacement for ${STR:6:-1} if STR is guaranteed to contain at least 7 characters. If it could be shorter, this will also cause OS X bash to complain about negative lengths, or go horribly wrong on bash versions that support negative lengths being taken as from-the-right offsets.

0

Googled from here:

They say ${STR:6:$#-1} should work well

In my case, with a similar error ${VERSION::-2}, it simply started to work after adding 0 like this: ${VERSION:0:-2}.

Glorfindel
  • 4,158