Bash 4.3 Substring Negative Length on OS X

12

2

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?

Brent Faust

Posted 2016-01-29T22:42:10.647

Reputation: 398

1http://tldp.org/LDP/abs/html/abs-guide.html#BASH2 - what was added when, starting with v2, v3 and v4 follows. – Hannu – 2016-01-30T03:42:11.060

@Hannu yes, that document says that the negative length semantics were added in version 4.2 – Brent Faust – 2016-01-31T03:21:41.267

I have the same issue : did you find a way to deal with that ? – Romain Jouin – 2017-01-03T13:50:45.270

@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 – 2017-02-12T02:44:04.003

1@Rubistro Just hit this :| One way around it is (in your example) echo "Hello World" | rev | cut -c -5 | rev – donovanmuller – 2017-04-14T23:51:01.367

Answers

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.

kayahr

Posted 2016-01-29T22:42:10.647

Reputation: 171

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.

flabdablet

Posted 2016-01-29T22:42:10.647

Reputation: 174

Thx, did the trick for me – Jean-Bernard Jansen – 2018-08-06T10:49:21.150

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

Aleksei Tselishchev

Posted 2016-01-29T22:42:10.647

Reputation: 1