help-bash
[Top][All Lists]
Advanced

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

Re: [Help-bash] opposite of 'shift'


From: Steven W. Orr
Subject: Re: [Help-bash] opposite of 'shift'
Date: Fri, 17 Feb 2012 08:49:48 -0500
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.26) Gecko/20120129 Thunderbird/3.1.18

On 2/17/2012 8:25 AM, Pierre Gaston wrote:


On Thu, Feb 16, 2012 at 10:56 PM, Dan Douglas <address@hidden
<mailto:address@hidden>> wrote:

    On Thursday, February 16, 2012 09:35:28 AM Greg Wooledge wrote:
     > On Thu, Feb 16, 2012 at 08:26:59AM -0600, Dan Douglas wrote:
     > > You can't. nonlocal positional parameters are inacceessable.
     > parameters.  (I gave two example input arrays.)  Sorry for the confusion.

    Ah, misinterpreted.

    But for arrays, it's almost worse!


This is probably because bash lacks an easy way to pass an array by reference
to a function.

This feature is a something people rather often ask for on IRC. Usually they
are implementing libraries for array manipulation (not sure if they actually
use these in the real world though)


This discussion has gone on for a bit too long. If you get good enough to want an unshift, then you should get good enough to write it yourself and not expect it to be implemented as a builtin. Having said that, I'd like to offer a couple of points on how some things can help to use arrays in bash in a pass-by-reference type of context. (We used to call it pass-by-name.)

I know this is ugly, and it might be considered dangerous, but here's a snippet of something I wrote which gets the name of an array and operates on it. It's about how to de-reference it without ksh's functionality.

print_array()
{
    typeset aname
    typeset -i size
    typeset -a vals
    typeset -i OPTIND=1
    typeset -i OPTERR=0
    typeset OPTARG
    typeset -i seen_q=0
    typeset opt

    while getopts :q opt "$@"
    do
        case $opt in
        q)
            seen_q=1
            ;;
        *)
            die "print_array:Unknown option: ${@:((OPTIND-1)):1}"
            ;;
        esac
    done
    shift $(( OPTIND - 1 ))

    while (( $# ))
    do
        aname=$1
        size=0

        eval "address@hidden"
        if (( seen_q ))
        then
            eval "vals=(\"address@hidden//\"/\\\\\"}\")"
        else
            eval "vals=(\"address@hidden")"
        fi
        # We have the name, the size and the values.
        # To print it all out, we use
        # an echo -n for the name and the size.
        # Then we use a printf with a single %s.
        # That %s is used on each element
        # of the array. The element is surrounded by double
        # quotes and is given
        # a trailing space.
        # Last, an empty echo prints a newline. The newline can't be put into
        # the printf or else it would cause each element to be
        # on its own line.
        echo -n "print_array:$aname:$size:"
        printf '"%s" ' "address@hidden"
        echo
        shift
    done
}

But the other thing that I'd like to offer is that bash supports dynamic scoping, as opposed to lexical scoping. In many cases, this my be a simple solution to your problem. OTOH, if it's not, the trick above is something I use on a regular basis. The other thing I'd like to recommend is this:

http://fvue.nl/wiki/Bash:_Passing_variables_by_reference

This is not for the faint of heart. I spent a week reading it, and more time after that re-writing it to take advantage of features in newer versions of bash. After that, I realized that there were things going on that I did *not* get right and I ended up fixing a few bugs that I had inadvertently introduced. Now, the functions upvar and upvars are my friends, but I use them with great care and respect. This is dangerous stuff if you don't *fully* understand how it works.

--
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net



reply via email to

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