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?

5
  • 1
    tldp.org/LDP/abs/html/abs-guide.html#BASH2 - what was added when, starting with v2, v3 and v4 follows.
    – Hannu
    Commented Jan 30, 2016 at 3:42
  • @Hannu yes, that document says that the negative length semantics were added in version 4.2 Commented Jan 31, 2016 at 3:21
  • I have the same issue : did you find a way to deal with that ? Commented Jan 3, 2017 at 13:50
  • @romainjouin Just by changing the algorithm. This syntax just doesn't work under OX X, even as of Bash version 4.3.46! Up-vote the question to try to get more eyes on this. Somebody knows the answer... Commented Feb 12, 2017 at 2:44
  • 1
    @Rubistro Just hit this :| One way around it is (in your example) echo "Hello World" | rev | cut -c -5 | rev Commented Apr 14, 2017 at 23:51

4 Answers 4

11

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.

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.

1
1

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.

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}.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .