Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[zsh] How to pop last argument to script?

445 views
Skip to first unread message

kj

unread,
Apr 9, 2012, 4:54:33 PM4/9/12
to


perl's 'pop' builtin can be used to remove the last element of an
array. In the example one-liner below, I use it to pop the last
command-line argument:

% perl -le 'print "@ARGV"; $x=pop @ARGV; print "$x @ARGV"' foo bar baz
foo bar baz
baz foo bar

Similarly, I want to be able to "pop" the last command-line argument
to a shell script (that receives a variable number of arguments)
in a way that allows me to capture the popped argument in a separate
variable, and leaves all the remaining arguments in $*, exactly as
they were originally passed to the script. (Just to be clear:
after this operation the number of arguments in $* should decrease
by exactly 1.)

How can I do this?

(I was surprised by how difficult it is just to *read* the last
argument of a shell script in such situations. I finally settled
with

eval 'LASTARG=$'$#

which, crazy as it may look, is actually the *least* crazy-looking
of all the alternatives I found, and it works in several shells.
Unfortunately this solves only half of the "pop" problem: I have
not yet removed the the last argument from $*. It crossed my mind
to assign a new value to $# [perl supports such an idiom for resizing
arrays], but I can't think of a way to do this!)

Thanks!

k

Alan Curry

unread,
Apr 9, 2012, 6:53:59 PM4/9/12
to
In article <jlvia8$rfa$1...@reader1.panix.com>, kj <no.e...@please.post> wrote:
>
>
>perl's 'pop' builtin can be used to remove the last element of an
>array. In the example one-liner below, I use it to pop the last
>command-line argument:
>
> % perl -le 'print "@ARGV"; $x=pop @ARGV; print "$x @ARGV"' foo bar baz
> foo bar baz
> baz foo bar
>
>Similarly, I want to be able to "pop" the last command-line argument
>to a shell script (that receives a variable number of arguments)
>in a way that allows me to capture the popped argument in a separate
>variable, and leaves all the remaining arguments in $*, exactly as
>they were originally passed to the script. (Just to be clear:
>after this operation the number of arguments in $* should decrease
>by exactly 1.)
>
>How can I do this?
>
>(I was surprised by how difficult it is just to *read* the last
>argument of a shell script in such situations. I finally settled
>with
>
> eval 'LASTARG=$'$#

zsh recognizes negative array indexes much like perl, and keeps the command
line arguments in an array called argv, so you can just use $argv[-1]. This
will cause an error if the array is empty, but you can avoid that by using
a range index: $argv[-1,-1]

As for the pop operation, the best I can think of is just an assignment with
a range index from the first to the next-to-last:

argv=($argv[1,-2])

>
>which, crazy as it may look, is actually the *least* crazy-looking
>of all the alternatives I found, and it works in several shells.
>Unfortunately this solves only half of the "pop" problem: I have
>not yet removed the the last argument from $*. It crossed my mind
>to assign a new value to $# [perl supports such an idiom for resizing
>arrays], but I can't think of a way to do this!)

Sometimes, rewriting a shell script in perl is just the correct answer.

--
Alan Curry

bsh

unread,
Apr 9, 2012, 9:28:59 PM4/9/12
to
KJ wrote:
> perl's 'pop' builtin can be used to remove the last element of an
> array.

Ah, brings to mind the heady days of vituperative comparisons
between perl(1) and shell....

> Similarly, I want to be able to "pop" the last command-line argument
> to a shell script (that receives a variable number of arguments)
> in a way that allows me to capture the popped argument in a separate
> variable, and leaves all the remaining arguments in $*, exactly as
> they were originally passed to the script. (Just to be clear:
> after this operation the number of arguments in $* should decrease
> by exactly 1.)
> How can I do this?

(*Sigh!* Why do they never indicate the shell being used, or
the code desired?...)

A portable, robust, and reasonably quick programmatic idiom is:

eval "LASTARG=\${$#}\"; set -- \"\$@\" \"\$@\"; shift $#+1"

"shift $#+1" utilizes ksh(1)'s feature of implicit arithmetric
evaluation on the argument to "shift". Other shells will require
explicit arithmetric evaluation, e.g. "$(($#+1))" or "$[$#+1]"
or even "`expr $# + 1`". Also, remember the "--"!! (Can you
guess why?)

(This is "reasonably quick" because utilizing argv with a
non-trivial argc can get relatively inefficient -- but this
is not the shell's fault).

You would just not believe how I came to "invent" this idiom:
I actually presumed to accomplish LALR(1) parsing in
shellscript! What was I thinking! (Actually, I came rather
close).

Although I saw it retroactively, the above is reminiscent of
the solution that DGK himself uses in his demonstration code
for pushd:

# http://www.kornshell.com/examples/pushpopdirs
# implementation of "push +n":
type=${1#+} i=_push_top-1
set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
shift $type
for dir
do (((i=i+1) < _push_max)) || break
_push_stack[i]=$dir
done

> (I was surprised by how difficult it is just to *read* the last
> argument of a shell script in such situations. I finally settled
> with: eval 'LASTARG=$'$#

Synonymous, but much more robust, is:

eval LASTARG=\${$#}

Because, even in ksh(1), positional parameters greater than 9
(that is, a two-or-more digit number) must be tokenized with
curly braces for backwards compatibility with bourne shell.
For instance, use "${10}" so as to distinguish it from being
parsed as "${1}0".

> which, crazy as it may look, is actually the *least* crazy-looking
> of all the alternatives I found, and it works in several shells.
> Unfortunately this solves only half of the "pop" problem: I have
> not yet removed the the last argument from $*. It crossed my mind
> to assign a new value to $# [perl supports such an idiom for resizing
> arrays], but I can't think of a way to do this!)

However, much better is the use of ksh93(1), which has much
enhanced array handling, requiring much less confabulation and
munging.

From the ksh(1) FAQ (http://www.kornshell.com/doc/faq.html):

Q: How can I shift the elements of an array?
A: The "shift" special builtin command only works for
positional parameters. However, noting that array subscripts
start at 0, you can use:
set -A name "${name[@]:1}"
... to shift the array.
--

Firstly, one does not have to make side-effects upon argv,
and secondly, individual array elements (INCLUDING argv)
can be manipulated in place. It is worth checking out its
features in the manpage.

=Brian

kj

unread,
Apr 9, 2012, 10:30:34 PM4/9/12
to
In <bdd16567-343a-4116...@iu9g2000pbc.googlegroups.com> bsh <brian...@rocketmail.com> writes:

>KJ wrote:

>(*Sigh!* Why do they never indicate the shell being used, or
>the code desired?...)

I don't know where you read my post, but in the original one that
I posted to comp.unix.shell, "[zsh]" appears clearly in the subject
line. I am rather annoyed not only by the unfair accusation, but
by the fact that this thread is now split into two, just because
someone decided to change its subject line...

k

Eric

unread,
Apr 10, 2012, 2:58:23 AM4/10/12
to
I don't think anyone "decided" - some software strips anything in square
brackets out of subjects because it's taken to be an unnecessary group
identifier. On the other hand, if your reader shows 2 threads it isn't
doing threading properly!

Eric

--
ms fnd in a lbry

Janis Papanagnou

unread,
Apr 10, 2012, 3:10:20 AM4/10/12
to
On 10.04.2012 04:30, kj wrote:
> In <bdd16567-343a-4116...@iu9g2000pbc.googlegroups.com> bsh <brian...@rocketmail.com> writes:
>
>> KJ wrote:
>
>> (*Sigh!* Why do they never indicate the shell being used, or
>> the code desired?...)
>
> I don't know where you read my post, but in the original one that
> I posted to comp.unix.shell, "[zsh]" appears clearly in the subject
> line.

Indeed. But I have to support poster bsh because that tag could
easily be overseen[*] and the body should be complete with its
description anyway. So instead of complaining about others you
could have contributed for clarity as well.

Thanks for your understanding.

Janis

> I am rather annoyed not only by the unfair accusation, but
> by the fact that this thread is now split into two, just because
> someone decided to change its subject line...
>
> k

[*] I also started to write a suggestion to use

eval last=\${$#}
echo $last
echo "${@:1: $#-1}"

But while that works in ksh and bash it does not work with zsh.

Stephane Chazelas

unread,
Apr 10, 2012, 6:04:06 AM4/10/12
to
2012-04-10 09:10:20 +0200, Janis Papanagnou:
[...]
> eval last=\${$#}
> echo $last
> echo "${@:1: $#-1}"
>
> But while that works in ksh and bash it does not work with zsh.

Of course, zsh has a proper array and string indexing with
$var[x,y] just like in other languages. ${var:xxx} historically
is csh's expansion flags. ksh used it for something else because
of its awkward array design. See how bash copied ksh for that
and is therefore missing on the csh expansion (which it supports
everywhere except in variable expansion).

In zsh:

a=(a b c)
last_element=$a[-1]

# popping:
a[-1]=()

# popping 2:
a[-2,-1]=()

--
Stephane

Stephane Chazelas

unread,
Apr 10, 2012, 12:07:07 PM4/10/12
to
2012-04-10 09:10:20 +0200, Janis Papanagnou:
> On 10.04.2012 04:30, kj wrote:
> > In <bdd16567-343a-4116...@iu9g2000pbc.googlegroups.com> bsh <brian...@rocketmail.com> writes:
> >
> >> KJ wrote:
> >
> >> (*Sigh!* Why do they never indicate the shell being used, or
> >> the code desired?...)
> >
> > I don't know where you read my post, but in the original one that
> > I posted to comp.unix.shell, "[zsh]" appears clearly in the subject
> > line.
>
> Indeed. But I have to support poster bsh because that tag could
> easily be overseen[*] and the body should be complete with its
> description anyway. So instead of complaining about others you
> could have contributed for clarity as well.
[...]

I'm totally on the OP's side on this. Using [flags] in the
subject of usenet messages to qualify/refine the context of
threads has been the recommanded way for decades. If you put
that information in the body, it will be lost eventually with
quote trimming.

A usenet software that automatically removes those tags is
definitely broken.

--
Stephane

kj

unread,
Apr 10, 2012, 12:56:43 PM4/10/12
to
In <jlvpa7$60c$1...@speranza.aioe.org> pac...@kosh.dhis.org (Alan Curry) writes:

>zsh recognizes negative array indexes much like perl, and keeps the command
>line arguments in an array called argv, so you can just use $argv[-1]. This
>will cause an error if the array is empty, but you can avoid that by using
>a range index: $argv[-1,-1]

This is very useful, thank you.

>As for the pop operation, the best I can think of is just an assignment with
>a range index from the first to the next-to-last:

>argv=($argv[1,-2])

This is definitely saner than what my trial-and-error scramble
eventually produced:

# poor-man's pop:
eval "LASTARG=\$$#; \$$#=()"

>Sometimes, rewriting a shell script in perl is just the correct answer.

That's very true, but in this particular case that I'm dealing with
at the moment, the prospect is daunting for its own reasons. The
pain of sticking with zsh will have to get significantly worse to
make me change tacks.

Thanks again!

kj

Janis Papanagnou

unread,
Apr 10, 2012, 1:03:59 PM4/10/12
to
I did not say to omit the tag(s) in the subject line.

Janis

Eric

unread,
Apr 10, 2012, 3:25:56 PM4/10/12
to
On 2012-04-10, Janis Papanagnou <janis_pa...@hotmail.com> wrote:
> Indeed. But I have to support poster bsh because that tag could
> easily be

> overseen

I think you might have meant "overlooked".

> [*] and the body should be complete with its
> description anyway. So instead of complaining about others you
> could have contributed for clarity as well.

Eric

unread,
Apr 10, 2012, 3:32:31 PM4/10/12
to
On 2012-04-10, Stephane Chazelas <stephane...@gmail.com> wrote:
>
> I'm totally on the OP's side on this. Using [flags] in the
> subject of usenet messages to qualify/refine the context of
> threads has been the recommanded way for decades. If you put
> that information in the body, it will be lost eventually with
> quote trimming.
>
> A usenet software that automatically removes those tags is
> definitely broken.

Indeed it is.

bsh

unread,
Apr 11, 2012, 10:00:06 PM4/11/12
to
Eric <e...@deptj.eu> wrote:
> Stephane Chazelas <stephane.chaze...@gmail.com> wrote:

> > A usenet software that automatically removes those tags is
> > definitely broken.
> Indeed it is.

After more than just a bit of investigation (I actually had to browse
the raw message text to indeed confirm that the "[zsh]" text tag
in question has indeed been stripped from the subject line.

That tag appears neither in the message title to the Webapp,
or the "annotated" message link.

Reading RFC-5536 and RFC-5537 not only did not provide any
information, both deteminately indicates no significance to either
left or right angle brackets in NetNews message formats. Hmm.

I therefore conclude that Google (I use Google's Groups/Usenet/
NetNews Webapp frontend) is purposely stripping these tags.
Normally, I would join in on a chorus of tongue-clucking, but
Google's Web software is of a sufficiently and consistently high
quality that I instead suspect that they _had_ to do this to defend
against some obscure use-case or security concern -- possibly
(and impossible to confirm without much more effort) a
ramification with their SOAP intranetworking.

Google is about to overhaul their entire Groups Webapp --
something for which I sent an elicited pithy comment about
looks versus functionality just two days ago.... Pertainent?

I suppose that I could experiment posting myself and browsing
developers forums, but is enough for today. It is strange,
however, that I have never seen (noticed?) this behavior
until now, after having used Google Groups for a decade.

=Brian

Janis Papanagnou

unread,
Apr 12, 2012, 2:25:00 AM4/12/12
to
On 12.04.2012 04:00, bsh wrote:
> Eric <e...@deptj.eu> wrote:
>> Stephane Chazelas <stephane.chaze...@gmail.com> wrote:
>
>>> A usenet software that automatically removes those tags is
>>> definitely broken.
>> Indeed it is.
>
> After more than just a bit of investigation (I actually had to browse
> the raw message text to indeed confirm that the "[zsh]" text tag
> in question has indeed been stripped from the subject line.
>
> [...]
>
> I therefore conclude that Google (I use Google's Groups/Usenet/
> NetNews Webapp frontend) is purposely stripping these tags.

Yes, Goo*** Soups does so. Complaints have been placed since long
(years!) now, but despite a few even fundamental changes in their
web software they seem to have changed nothing in that respect.

My suspicion was that they use [tagging] for their own internal
business and it conflicts with the long standing Usenet tagging
conventions. They don't seem to care much.

Some folks proposed to use {tagging} instead. Others prefer to
just ignore Goo*** Soups and switch to a (real) newsreader.

Janis

> [...]

Ed Morton

unread,
Apr 13, 2012, 4:34:36 PM4/13/12
to
kj <no.e...@please.post> wrote:

>
>
> perl's 'pop' builtin can be used to remove the last element of an
> array. In the example one-liner below, I use it to pop the last
> command-line argument:
>
> % perl -le 'print "@ARGV"; $x=pop @ARGV; print "$x @ARGV"' foo bar baz
> foo bar baz
> baz foo bar
>
> Similarly, I want to be able to "pop" the last command-line argument
> to a shell script (that receives a variable number of arguments)
> in a way that allows me to capture the popped argument in a separate
> variable, and leaves all the remaining arguments in $*, exactly as
> they were originally passed to the script. (Just to be clear:
> after this operation the number of arguments in $* should decrease
> by exactly 1.)
>
> How can I do this?

I expect this will work:

lastarg="\$$#"
for (( argNr=1; argNr<$#; argNr++ )); do
eval args[$argNr]="\$$argNr"
done

set -- "${args[@]}"

Just tweak "argNr<$#" if you want to pop more than one arg at a time.

Something to consider: should popping the last "arg" from "cmd -x 3" give
the same result as popping it from "cmd -x3"? If so, look into getopts...

Regards,

Ed.

Posted using www.webuse.net

bsh

unread,
Apr 16, 2012, 5:09:17 PM4/16/12
to
Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
> bsh wrote:
> > Eric <e...@deptj.eu> wrote:
> > > Stephane Chazelas <stephane.chaze...@gmail.com> wrote:

> Yes, Goo*** Soups does so. Complaints have been placed since long
> (years!) now, but despite a few even fundamental changes in their
> web software they seem to have changed nothing in that respect.

"Soups"?

> My suspicion was that they use [tagging] for their own internal
> business and it conflicts with the long standing Usenet tagging
> conventions. They don't seem to care much.

As per my own conjecture?

> Some folks proposed to use {tagging} instead. Others prefer to
> just ignore Goo*** Soups and switch to a (real) newsreader.

Until you say this now, I had no idea that this was happening, and
now I wonder how long or often it has affected my ability to make a
pertainent reply. I have used Google Groups for many years, and
until you mention this, had even no idea that it was a going concern.

Just one more thing, if you wouldn't mind, Janis: is there a known
link or resource where you could point me that discusses the issue
as is your experience?

=Brian

Janis Papanagnou

unread,
Apr 16, 2012, 6:06:32 PM4/16/12
to
On 16.04.2012 23:09, bsh wrote:
> Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
[...]
>> Some folks proposed to use {tagging} instead. Others prefer to
>> just ignore Goo*** Soups and switch to a (real) newsreader.
>
> Until you say this now, I had no idea that this was happening,

You mean the {tag} proposal? Or the suggestion to switch newsreader?

The former proposal I've seen in rec.games.roguelike.nethack, and I
recall it's been proposed by a guy called Kent Paul Dolan; I haven't
heard from him now for a long time, he's quite old. I didn't find it
a good way to solve a Google issue, though.

The latter proposal, a no-brainer(?), you can probably find in many
newsgroups.

> and
> now I wonder how long or often it has affected my ability to make a
> pertainent reply. I have used Google Groups for many years, and
> until you mention this, had even no idea that it was a going concern.

Quite from the beginning (as far as memory serves) google has issues
with his new service. Every new release seemed to have introduced
new bad interface changes (sometimes also coupled with improvements,
to be fair).

> Just one more thing, if you wouldn't mind, Janis: is there a known
> link or resource where you could point me that discusses the issue
> as is your experience?

I can't. It's been mentioned from time to time in (since many years
now) in various Usenet newsgroups. From there I got the information
that some folks also file bug reports at Google, but it seems to no
avail.

I am uncertain about your intention, why you think that information
about ongoing complaints would help you in any way. Mind to explain?

Janis

>
> =Brian

Janis Papanagnou

unread,
Apr 16, 2012, 6:15:54 PM4/16/12
to
On 16.04.2012 23:09, bsh wrote:
> Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
>
>> Yes, Goo*** Soups does so.
>
> "Soups"?

A malapropism.

Janis

Robert Bonomi

unread,
Apr 17, 2012, 5:34:40 AM4/17/12
to
In article <702b0e4f-b1ab-4046...@qg3g2000pbc.googlegroups.com>,
bsh <brian...@rocketmail.com> wrote:
>Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
>
>> Yes, Goo*** Soups does so. Complaints have been placed since long
>> (years!) now, but despite a few even fundamental changes in their
>> web software they seem to have changed nothing in that respect.
>
>"Soups"?

Mrs. Malaprop's reference for Gargle Gropes.


Loki Harfagr

unread,
Apr 17, 2012, 1:14:06 PM4/17/12
to
Tue, 17 Apr 2012 04:34:40 -0500, Robert Bonomi did cat :
and I'd bet this deference was quite comprehensible for
people from the world that might not have sturdied Shere Khan plays ;-)

Robert Bonomi

unread,
Apr 17, 2012, 7:00:06 PM4/17/12
to
In article <pan.2012.04...@thedarkdesign.free.fr.INVALID>,
The Rivals for gauging obscure references say "Baloo-ny". *snicker*

Oldest reference to the penultimate/ultimate word pair in my explanation
is, according to 'dejanews++', over five years ago -- January 2, 2007.

Entering the lady's name in the same tool is also 'educational'. ;)

I prefer responses that are *both* informative and educational.

Loki Harfagr

unread,
Apr 19, 2012, 3:19:13 AM4/19/12
to
Tue, 17 Apr 2012 18:00:06 -0500, Robert Bonomi did cat :

> In article <pan.2012.04...@thedarkdesign.free.fr.INVALID>,
> Loki Harfagr <l0...@thedarkdesign.free.fr.INVALID> wrote:
>>Tue, 17 Apr 2012 04:34:40 -0500, Robert Bonomi did cat :
>>
>>> In article
>><702b0e4f-b1ab-4046...@qg3g2000pbc.googlegroups.com>,
>>> bsh <brian...@rocketmail.com> wrote:
>>>>Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
>>>>
>>>>> Yes, Goo*** Soups does so. Complaints have been placed since long
>>>>> (years!) now, but despite a few even fundamental changes in their
>>>>> web software they seem to have changed nothing in that respect.
>>>>
>>>>"Soups"?
>>>
>>> Mrs. Malaprop's reference for Gargle Gropes.
>>
>>and I'd bet this deference was quite comprehensible for
>>people from the world that might not have sturdied Shere Khan plays ;-)
>
> The Rivals for gauging obscure references say "Baloo-ny". *snicker*

gesundheit :D)

>
> Oldest reference to the penultimate/ultimate word pair in my explanation
> is, according to 'dejanews++', over five years ago -- January 2, 2007.

strange, I find at least two older threads, that one is circa 2004:
8t90o0dfa5k864840rud5vaqh7ia4q819v


>
> Entering the lady's name in the same tool is also 'educational'. ;)
>
> I prefer responses that are *both* informative and educational.

well, depends if you're playing with primary classes or postgrad,
you may hope for some curiosity in at least one of these groups ;-)

Ivan Shmakov

unread,
Apr 23, 2012, 12:03:20 AM4/23/12
to
>>>>> Janis Papanagnou <janis_pa...@hotmail.com> writes:
>>>>> On 12.04.2012 04:00, bsh wrote:

[Cross-posting to news:news.software.readers, and setting
Followup-To: there as well.]

[...]

> Some folks proposed to use {tagging} instead. Others prefer to just
> ignore Goo*** Soups and switch to a (real) newsreader.

Which makes me wonder, is there a real newsreader implemented in
ECMAScript (or a dialect of)?

--
FSF associate member #7257

bsh

unread,
Apr 23, 2012, 6:56:42 PM4/23/12
to
Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
> bsh wrote:
> > Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
> > ...

> > Until you say this now, I had no idea that this was happening,
> You mean the {tag} proposal? Or the suggestion to switch newsreader?

Neither -- the issue being with the fact that I have used the Google
Groups webapp for years without the knowledge of this particular
problem.
It makes me wonder how many times it has compromised my ability
to fully understand the nature of the OQ.

> > Just one more thing, if you wouldn't mind, Janis: is there a known
> > link or resource where you could point me that discusses the issue
> > as is your experience?
> ...
> I am uncertain about your intention, why you think that information
> about ongoing complaints would help you in any way. Mind to explain?

I have no ulterior motive than to explore this issue. I do not intend
to
complain to Google.com, as I know what would come of that effort
(Nothing). Presumedly, "forewarned is forearmed" will have to be
sufficient in this regard.

=Brian

bsh

unread,
Apr 23, 2012, 6:58:57 PM4/23/12
to
Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
> bsh wrote:
> > Janis Papanagnou <janis_papanag...@hotmail.com> wrote:
> > > ...

> The former proposal I've seen in rec.games.roguelike.nethack, and I
> recall it's been proposed by a guy called Kent Paul Dolan; I haven't
> heard from him now for a long time, he's quite old. I didn't find it
> a good way to solve a Google issue, though.

And oh yes! I almost forgot to thank you for your information.

=Brian
0 new messages