12

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?

  • 1
    tldp.org/LDP/abs/html/abs-guide.html#BASH2 - what was added when, starting with v2, v3 and v4 follows. – Hannu Jan 30 '16 at 3:42
  • @Hannu yes, that document says that the negative length semantics were added in version 4.2 – Brent Faust Jan 31 '16 at 3:21
  • I have the same issue : did you find a way to deal with that ? – Romain Jouin Jan 3 '17 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... – Brent Faust Feb 12 '17 at 2:44
  • 1
    @Rubistro Just hit this :| One way around it is (in your example) echo "Hello World" | rev | cut -c -5 | rev – donovanmuller Apr 14 '17 at 23:51
7

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.

|improve this answer|||||
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.

|improve this answer|||||
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}.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.