help-bash
[Top][All Lists]
Advanced

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

Re: Use of $@


From: alex xmb ratchev
Subject: Re: Use of $@
Date: Tue, 21 Feb 2023 12:08:30 +0100

On Tue, Feb 21, 2023, 12:04 PM Kerin Millar <kfm@plushkava.net> wrote:

> On Tue, 21 Feb 2023 11:27:36 +0100
> Christof Warlich <cwarlich@gmx.de> wrote:
>
> > Hi,
> >
> > just to improve my bash skills: The following functions prints the array
> > index of a value if found:
> >
> > index() { local e="$1"; shift; local a=("$@"); for i in "${!a[@]}"; do
> > [[ ${a[$i]} != $e ]] || { echo $i; break; }; done; }
>

sorry didnt read , u wanted value back to key
declare -n ( named reference ) can also , without copying args

> Thus, with e.g.: myarray=("a" "bc" "my value" "z")
> >
> > I get:
> >
> > $ index "my value" "${myarray[@]}"
> > 2
> >
> > as expected. The only thing that bothers me is that I couldn't get away
> > without the intermediate assignment of $@ to a new array (a): Is there
> > really no way to avoid that, i.e. directly using $@ in the for-loop?
>
> Unfortunately, the function is incorrect to begin with.
>
> $ myarray=(foo bar baz)
> $ index bar "${myarray[@]}"
> 1
> $ unset -v 'myarray[0]'
> $ declare -p myarray
> declare -a myarray=([1]="bar" [2]="baz")
> $ index bar "${myarray[@]}"
> 0
>
> Indeed, to correctly encapsulate the intended functionality with a
> function is a tremendously awkward affair in bash. One option would be to
> pass the array by its name rather than as its expanded elements, then make
> use of a nameref in the function. Unfortunately, namerefs are poorly
> implemented in bash [1] [2]. Should you wish to try it anyway, here is an
> example.
>
> index() {
>         local i e="$1"
>         local -n _ref="$2"
>         shift
>         for i in "${!_ref[@]}"; do
>                 if [[ ${_ref[i]} == "$e" ]]; then
>                         printf '%s\n' "$i"
>                         return 0
>                 fi
>         done
>         return 1
> }
>
> $ declare -p myarray
> declare -a myarray=([1]="bar" [2]="baz")
> $ index bar myarray
> 1
>
> One of the many issues with namerefs is that they can easily be undone by
> a (variable) name space conflict. I do not know which underlying problem
> the function is intended to solve but it is quite possible that, whatever
> it may be, you might benefit from using an associative array [1]. Not
> least, an associative array could easily be made to store a 'reverse' map
> of elements to index numbers.
>
> On the other hand, if you are entirely certain that the function will only
> ever have to contend with non-sparse arrays in your program, you could just
> loop over the positional parameters ("$@") and use an incrementing counter
> variable to identify the appropriate index number.
>
> P.S. The right-hand side of == in [[ is treated as a globbing pattern if
> not appropriately quoted.
>
> [1] http://mywiki.wooledge.org/BashFAQ/006
> [2] https://gist.github.com/ormaaj/5682807
>
> --
> Kerin Millar
>
>


reply via email to

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