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

wishlist: an absolute ESC .

23 views
Skip to first unread message

Dan Jacobson

unread,
Dec 23, 2005, 10:14:14 PM12/23/05
to bug-...@gnu.org
How can one make a "ESC ." command that will get the last word from
the last line, even if we have just hit a few ^P's?


Chet Ramey

unread,
Dec 24, 2005, 12:52:00 PM12/24/05
to Dan Jacobson, bug-...@gnu.org, ch...@case.edu
Dan Jacobson wrote:
> How can one make a "ESC ." command that will get the last word from
> the last line, even if we have just hit a few ^P's?

You'll have to modify the source, since ^P changes your position in
the history list.

Chet

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
( ``Discere est Dolere'' -- chet )
Live Strong.
Chet Ramey, ITS, CWRU ch...@case.edu http://cnswww.cns.cwru.edu/~chet/


Dan Jacobson

unread,
Dec 28, 2005, 8:43:15 AM12/28/05
to bug-...@gnu.org
The man page berates old-timers:
When the old-style backquote form of substitution is used...
However, who is it that is too hungry for the next ")"?:
$ k=$(case x in x) :;; esac)
bash: syntax error near unexpected token `;;'
$ k=$(case x in x) :; esac)
bash: syntax error near unexpected token `esac'
$ k=`case x in x) :; esac`
$
The man page even mentions:
Command substitutions may be nested. To nest when using the
backquoted form, escape the inner backquotes with backslashes.
But tripping/conflict over case esac innards hadn't been discovered
until today for $() so isn't mentioned. Fix the "bug" or mention it
here and in the "case ... esac" sections of all docs.

By the way,


>> How can one make a "ESC ." command that will get the last word from
>> the last line, even if we have just hit a few ^P's?

C> You'll have to modify the source, since ^P changes your position in
C> the history list.

(It is more likely that the source will modify me. Anyway, I end up
pasting with the mouse 30 times a day. I have only once in my life
used ^R.....ESC. or ^P^P^P...ESC. as offered.)


Eric Blake

unread,
Dec 28, 2005, 1:04:29 PM12/28/05
to Dan Jacobson, bug-...@gnu.org
> However, who is it that is too hungry for the next ")"?:
> $ k=$(case x in x) :;; esac)
> bash: syntax error near unexpected token `;;'
> $ k=$(case x in x) :; esac)
> bash: syntax error near unexpected token `esac'
> $ k=`case x in x) :; esac`

I believe this is a bug in bash 3.0. I have confirmed that
it still exists in bash-3.1-beta1, but have not yet tested
if bash 3.1 final patchlevel 1 has fixed the bug. POSIX requires
(http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03)
that in the $(command) form, "Any valid shell script can be
used for command."

The rationale page (http://www.opengroup.org/onlinepubs/009695399/xrat/xcu_chap02.html)
then proceeds to list several examples of $() commands where
an unmatched ')' can appear inside the nested command, when used
as part of a valid shell script (although it did not list the example
of case with unmatched ')'). Furthermore, the rationale page states
under the Case Conditional Construct:

"At one time, using the leading parenthesis was required if the case
statement was to be embedded within a "$()" command substitution;
this is no longer the case with the POSIX shell."

Therefore, I read this as stating that POSIX requires your example
to succeed, and that bash has a bug (FYI, the bug also appears
in my installed versions of zsh and ksh).

Meanwhile, as a workaround, use:

$ k=$(case x in (x) :; esac)

--
Eric Blake


Eric Blake

unread,
Dec 28, 2005, 2:00:23 PM12/28/05
to Dan Jacobson, bug-...@gnu.org
> I have confirmed that
> it still exists in bash-3.1-beta1, but have not yet tested
> if bash 3.1 final patchlevel 1 has fixed the bug.

My results: bash 3.1, with or without patch 1, still has
the bug.

$ k=$(case x in x) echo hi; esac)


bash: syntax error near unexpected token `esac'

> The rationale page

> (http://www.opengroup.org/onlinepubs/009695399/xrat/xcu_chap02.html)
> then proceeds to list several examples of $() commands where
> an unmatched ')' can appear inside the nested command, when used

> as part of a valid shell script.

Of which, bash gets 2 of the three examples WRONG:

Required:
$ echo $(
> cat <</eof
> a here-doc with )
> eof
> )
a here-doc with )
$ echo $(
> echo abc # a comment with )
> )
abc
$ echo $(
> echo ')'
> )
)

bash 3.0.16:
$ echo $(
> cat << /eof
> a here-doc with )
a here-doc with
$ # oops, the ) in the here-doc was consumed to close the $(), and
$ # without a warning of a missing eof delimiter
$ echo $(
> echo abc # a comment with )
abc
$ # oops, the ) in the comment was consumed to close the $()
$ echo $(
> echo ')'
> )
)
$ # The only correct answer of the three

bash 3.1.1:
$ echo $(
> cat << /eof
> a here-doc with )
a here-doc with
$ # oops, the ) in the here-doc was consumed to close the $(), and
$ # without a warning of a missing eof delimiter
$ echo $(
> echo abc # a comment with )
> )
abc
)
$ # oops, an extra ) snuck through to the outer echo
$ echo $(
> echo ')'
> )
)
$ # The only correct answer of the three

--
Eric Blake


Eric Blake

unread,
Jan 2, 2006, 5:14:38 PM1/2/06
to bug-...@gnu.org, jid...@jidanni.org
> Eric> $ k=$(case x in (x) :; esac)
> Huh, they only taught us ) in school.
> Is () since Bell Labs days too?

POSIX requires shells to support case x in (x), but older
bourne shells do not support this newer syntax. That is
probably why you were not taught it; if I understand
correctly, it was invented in ksh, then standardized by
POSIX, which is why bash now has it. At any rate,
several platforms, including Solaris' /bin/sh, still do not
parse ( in case patterns even today, so it is certainly
not portable if you don't have access to a POSIX shell.

> P.S. I didn't test <<\EOF with ")" itself as the EOF marker,
> <<\( maybe. You can... Reply-To: bug-...@gnu.org, jid...@jidanni.org

Indeed, this points out another (probably related) parsing
problem in bash 3.1:

Buggy (here-doc delimiter treated as $() closer):
$ echo $(
> cat << ')'
> hello
> )
hello

Expected:
$ echo $(
> cat << ')'
> hello
> )
> )
hello

--
Eric Blake


Sven Mascheck

unread,
Jan 3, 2006, 1:51:36 PM1/3/06
to bug-...@gnu.org
Eric Blake in <mailman.21142.11362...@gnu.org>:

> several platforms, including Solaris' /bin/sh, still do not
> parse ( in case patterns even today, so it is certainly
> not portable if you don't have access to a POSIX shell.

Even if they parsed it, it wouldn't be portable,
because no traditional Bourne shell knows $().

Interestingly even the traditional Almquist shell on
4BSD didn't parse it, although $() was added already.
(mainly a SVR4 sh clone and not to confuse with its
current successors.)

(BTW, I liked your idea of testing the examples and collected
some results on http://www.in-ulm.de/~mascheck/various/cmd-subst/)
--
[i'm trying the list after having problems with the gateway]


0 new messages