help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Awkward behavior of empty arrays


From: DJ Mills
Subject: Re: [Help-bash] Awkward behavior of empty arrays
Date: Thu, 31 Aug 2017 12:23:22 -0400

Use case for "$*" (or similarly "${a[*]}"):

join() {
  local IFS=$1
  shift
  printf '%s\n' "$*"
}

arr=(foo bar baz)
join '+' "address@hidden"

With a change in IFS, the construct becomes rather useful

On Thu, Aug 31, 2017 at 12:16 PM, Andy Chu <address@hidden> wrote:

> On Thu, Aug 31, 2017 at 7:47 AM, Chet Ramey <address@hidden> wrote:
>
> >
> > > 1. Never use anything that isn't in parentheses on the RHS of an array
> > > initialization.
> >
> > This is essentially an attempt to avoid the implicit use of subscript 0.
> >
>
>
> Yes I'm suggesting a style where all implicit conversions are avoided (from
> the POV of someone coming from another programming language).  If you can
> see a case where implicit conversions happen using the rules I gave, that's
> a bug :)
>
> As I just wrote, avoiding
>
> declare -a A=x
>
> in favor of:
>
> declare -a A=(x)
>
> is analogous to avoiding "$A" in favor of "{$A[0]}".
>
>
>
> >
> >
> > > "${A[*]}"
> > > ${A[*]}
> > These are useful in the same way that $* and "$*" are useful.
> >
>
> I actually never use $* "$*" $@, or ${A[*]} "${A[*]}" address@hidden in any 
> of my
> programs.  I believe they can always be expressed using different (IMO
> clearer) mechanisms.
>
> Consider this:
>
> $ set -- foo '*.sh' bar
>
> There are only 3 possibilities from the four constructs (AFAICT $* is
> identical to $@):
>
> $ argv "$@"
> ['foo', '*.sh', 'bar']
>
> $ argv $@
> ['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']
>
> $ argv "$*"
> ['foo *.sh bar']
>
> $ argv
> $*
>
> ['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']
>
> These 3 possibilities can always be achieved as follows:
>
> $ argv "$@"
> ['foo', '*.sh', 'bar']
>
> $ joined="$@"  # explicit join
>
> $ argv "$joined"
> ['foo *.sh bar']
>
> $ argv $joined
> ['foo', 'bad.sh', 'local.sh', 'setup.sh', 'bar']
>
> So I have used nothing but "$@" to generate all 3 possibilities.  Similarly
> for "address@hidden".
>
>
>
> >
> >
> > > In particular, don't expect to compare arrays with [[.
> > >
> > > $ declare -a A=(A B C D)
> > > $ declare -a B=('A B' 'C D')
> > >
> > > $ echo "address@hidden"
> > > 4
> > > $ echo "address@hidden"
> > > 2
> > >
> > > # arrays compare equal because they're coerced to strings before
> > comparison
> > > $ [[ "address@hidden" == "address@hidden" ]]; echo $?
> > > 0
> >
> > Because the operands in [[ commands don't undergo word splitting.
> >
>
> Yes, it depends how you think about it from the implementation POV.  In
> OSH, variables are represented by a discriminated union (in ML-like
> syntax):
>
> value =
>     Undef
>   | Str(string s)
>   | StrArray(string* strs)
>
> So when I do [[ "address@hidden" == "address@hidden" ]], I actually have to 
> JOIN the
> arrays first to main compatibility with bash (there could be a flag to turn
> this off.)
>
> So it's not just lack of splitting, but ADDING joining (i.e. coerce an
> array to string).  But if bash stores arrays as FLAT strings internally,
> and only does splitting upon splicing into an argv array, then you can
> think of it as lack of splitting.
>
> Andy
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]