0

I am using Bourne Shell. Need to confirm if my understanding of following is correct?

$ echo $SHELL
/bin/bash

$ VAR="NJ:NY:PA" <-- declare an array with semicolon as separator?

$ echo ${VAR#*} <-- show entire array without separator?
NJ:NY:PA  

$ echo ${VAR#*:*} <-- show array after first separator?
NY:PA

$ echo ${VAR#*:*:*} <-- show string after two separator
PA
melpomene
  • 84,125
  • 8
  • 85
  • 148
oradbanj
  • 551
  • 7
  • 23
  • 1
    No, it's not. There are no arrays in your code. – melpomene Jun 02 '17 at 21:17
  • ok. So VAR is treated as string and echo is simply printing substring, by treating colon (:) as separator – oradbanj Jun 02 '17 at 21:20
  • Read the fine manual: https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion – melpomene Jun 02 '17 at 21:21
  • 1
    also that's not bourne, it's bash – George M Reinstate Monica Jun 02 '17 at 21:23
  • bash *or* POSIX sh, but certainly not Bourne. – Charles Duffy Jun 02 '17 at 21:25
  • This is *almost* a duplicate of https://stackoverflow.com/questions/2059794/what-is-the-meaning-of-the-0-syntax-with-variable-braces-and-hash-chara -- I'm sure we have an exact one somewhere. – Charles Duffy Jun 02 '17 at 21:26
  • ...btw, re: reference docs, you may find http://wiki.bash-hackers.org/syntax/pe more accessible than the manual. – Charles Duffy Jun 02 '17 at 21:26
  • BTW, putting a `*` on the end of that expansion form doesn't actually make much sense. There's no reason whatsoever to use `${var#*:*:*}` instead of `${var#*:*:}` -- since the single-`#` form expands to the **shortest** match possible, and `*` is allowed to expand to 0 characters, the final `*` does nothing. – Charles Duffy Jun 02 '17 at 21:32
  • ("Bourne Again" is a cute play on words, but Bourne is a shell from the 70s, whereas bash takes much more inspiration from ksh as it existed in the 80s, and *almost* complies with the 1992 POSIX sh specification, other than some very specific places -- such as `echo` -- where it takes liberties. They're from a different era, and calling bash "Bourne" pushes the truth). – Charles Duffy Jun 02 '17 at 21:36

1 Answers1

2

${var#pattern} is a parameter expansion that expands to the value of $var with the shortest possible match for pattern removed from the front of the string.

Thus, ${VAR#*:} removes everything up and including to the first :; ${VAR#*:*:} removes everything up to and including the second :.

The trailing *s on the end of the expansions given in the question don't have any use, and should be avoided: There's no reason whatsoever to use ${var#*:*:*} instead of ${var#*:*:} -- since these match the smallest amount of text possible, and * is allowed to expand to 0 characters, the final * matches and removes nothing.


If what you really want is an array, you might consider using a real array instead.

# read contents of string VAR into an array of states
IFS=: read -r -a states <<<"$VAR"
echo "${states[0]}"  # will echo NJ
echo "${states[1]}"  # will echo NY
echo "${#states[@]}" # count states; will emit 3

...which also gives you the ability to write:

printf ' - %s\n' "${states[@]}"  # put *all* state names into an argument list
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441