3
str=abcde
echo ${str:0:2} # output: ab
echo ${str::2} # outpub: ab

The code above leads to same result. As the documentation describes:

This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @ or *, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below. If length is omitted, it expands to the substring of the value of parameter starting at the character specified by offset and extending to the end of the value. length and offset are arithmetic expressions (see Shell Arithmetic).

If offset evaluates to a number less than zero, the value is used as an offset in characters from the end of the value of parameter. If length evaluates to a number less than zero, it is interpreted as an offset in characters from the end of the value of parameter rather than a number of characters, and the expansion is the characters between offset and that result. Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the :- expansion.

There is no description about omitting offset but in fact it can be omitted.

I wonder if there are any documents I haven't noticed.

kvantour
  • 25,269
  • 4
  • 47
  • 72
Lasy
  • 97
  • 9

2 Answers2

2

In the Arithmetic Evaluation section of the manual it is mentioned that a null value is interpreted as 0, and as we know the argument of that parameter expansion is subject to arithmetic evalation.

A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax.

A null value evaluates to 0.

This might be the closest reference you can get as to why an empty value evaluates to 0.

However, I still think that allowing empty arguments should still be documented.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • I agree with you that empty arguments should be documented. As I post in another answer, I'm confused whether empty arguments be considered to be a **variable** – Lasy Feb 07 '23 at 09:38
  • I think that doesn't apply: `A shell variable that is null or unset...`. Where is the shell variable here? `v=''; echo ${str:v:2}` would be ok but the section you quoted wouldn't apply to `${str::2}`. – M. Nejat Aydin Feb 07 '23 at 09:48
  • @M.NejatAydin It hints how internal evaluation of a value is processed. Regardless if it's coming from a parameter or a literal value, it gets commonly evaluated like it. The only thing that prevents evaluation of an empty value is the syntax parser that comes before it. `$(( '' ))` for example isn't allowed. – konsolebox Feb 07 '23 at 09:53
  • @Lazy The empty arguments are "arguments" and not variables. They are strings passed by the parser to the evaluator. – konsolebox Feb 07 '23 at 09:56
2

When you have a look at man bash you can read:

${parameter:offset}, ${parameter:offset:length} Substring Expansion. Expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below. If length is omitted, expands to the substring of the value of parameter starting at the character specified by offset and extending to the end of the value. length and offset are arithmetic expressions (see ARITHMETIC EVALUATION below).

It must be made clear that it is not possible to omit the offset value. Here, omit implies that also the <colon>-character is missing. From the table below, you see that there is an ambiguity in this case:

offset omitted offset
length ${parameter:offset:length} ${parameter:length}
omitted length ${parameter:offset} ${parameter}

From a syntactic point of view, you cannot omit length as you can not distinguish whether length or offset is omitted.

It is possible to leave it empty. man bash clearly states that both length and offset are arithmetic expressions and in that section we find.

A null value evaluates to 0.

This entails both unset variables as well as empty expressions:

$ unset v
$ echo $(( v )) $(( ))
0 0

As offset is a arithmetic expression, an empty value will valuate to the same value as $(( )) which is 0.

So the following are all equivalent:

${parameter:0:length} == ${paramter::length}
${parameter:offset:0} == ${parameter:offset:} == ""
${parameter:0:0} == ${parameter::} == ""
kvantour
  • 25,269
  • 4
  • 47
  • 72
  • I'm still confused. Does an empty `offset` is a **variable** ? Does an empty `offset` means **unset** or **null**? What is the difference between *empty* and *omitted*? – Lasy Feb 07 '23 at 09:31
  • 1
    I think that doesn't apply: `A shell variable that is null or unset...`. Where is the shell variable here? `v=''; echo ${str:v:2}` would be ok but the section you quoted wouldn't apply to `${str::2}`. – M. Nejat Aydin Feb 07 '23 at 09:47
  • @M.NejatAydin There might be some confusion here from the parts I copied. Since `offset` is a arithmetic evaluation, There were two parts, one part referencing a variable that is null or unset and another referencing null in general. Here `offset` is null in general. You can see it by attempting to execute `echo $(( ))`. It returns zero as the expression is NULL. – kvantour Feb 07 '23 at 10:12
  • @M.NejatAydin I've updated the text a bit. – kvantour Feb 07 '23 at 10:18
  • @Lasy the word omitted implies that the full string `:length` is omitted (including the colon). Empty would be `:` – kvantour Feb 07 '23 at 10:23
  • I think the problem with this quote ("A null value evaluates to 0") is that the term "null value" isn't defined. Isn't the `''` null value? Then why isn't `${str:'':2}` allowed? It is strange that bash allows `${str:"":2}` ! – M. Nejat Aydin Feb 07 '23 at 10:25
  • @M.NejatAydin my version of bash does not allow either of the two. – kvantour Feb 07 '23 at 10:36
  • My `$BASH_VERSION` expands to `5.2.15(1)-release` and allows `${str:"":2}` but doesn't `${str:'':2}`. Seems to be a bug. Still, why `${str:'':2}` isn't allowed remains a mystery to me. – M. Nejat Aydin Feb 07 '23 at 10:38
  • @M.NejatAydin I believe that `""` is allowed because of parameter expansion. Here `"${par}"` can evaluate to `""` while `'${par}'` will never expand. – kvantour Feb 07 '23 at 10:47
  • I cannot still fathom why `${str:'':2}` and `${str::2}` are not equivalent. – M. Nejat Aydin Feb 07 '23 at 11:05
  • 1
    @M.NejatAydin for the same reason it is not allowed in an arithmetic context: `$((''))` leads to `bash: '': syntax error: operand expected (error token is "''")` – Léa Gris Feb 07 '23 at 11:41
  • @LéaGrisL The question is: If a null value evaluates to 0 then why doesn't the `''` evaluate to 0? – M. Nejat Aydin Feb 07 '23 at 12:43
  • 1
    @M.NejatAydin See https://stackoverflow.com/questions/75373699/ – kvantour Feb 07 '23 at 13:05