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

Is it possiable to define alias for complex compound commands within bash?

65 views
Skip to first unread message

Hongyi Zhao

unread,
Jan 21, 2016, 2:37:45 AM1/21/16
to
Hi all,

I want to define the following alias:

alias ehgrep='awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color '

I.e., using ehgrep to invoking the following commands:

awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}' ~/.bash_eternal_history
| awk '!a[$0]++'|grep -E --color

But it seems both with single/double quotes grouping these commands will
failed. I mean, I tried the following two forms but both are failed to
work:

alias ehgrep='awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color '

or

alias ehgrep="awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "

So, Is it possiable to define alias for complex compound commands within
bash for my above case?

Regards
--
.: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.

Chris F.A. Johnson

unread,
Jan 21, 2016, 4:08:07 AM1/21/16
to
On 2016-01-21, Hongyi Zhao wrote:
> Hi all,
>
> I want to define the following alias:

man bash:
"For almost every purpose, aliases are superseded by shell functions."


--
Chris F.A. Johnson

Rakesh Sharma

unread,
Jan 21, 2016, 4:20:54 AM1/21/16
to
On Thursday, 21 January 2016 13:07:45 UTC+5:30, Hongyi Zhao wrote:
>
> alias ehgrep='awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
> ~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color '
>
> I.e., using ehgrep to invoking the following commands:
>
> awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}' ~/.bash_eternal_history
> | awk '!a[$0]++'|grep -E --color
>
> But it seems both with single/double quotes grouping these commands will
> failed. I mean, I tried the following two forms but both are failed to
> work:
>
> alias ehgrep='awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
> ~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color '
>
> or
>
> alias ehgrep="awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
> ~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "
>
> So, Is it possiable to define alias for complex compound commands within
> bash for my above case?
>

you need to replace all the inner single quotes as:
' -> ' \' '

but dont touch the outermost single quotes.

Hongyi Zhao

unread,
Jan 21, 2016, 5:27:02 AM1/21/16
to
On Thu, 21 Jan 2016 01:20:50 -0800, Rakesh Sharma wrote:

> you need to replace all the inner single quotes as:
> ' -> ' \' '
>
> but dont touch the outermost single quotes.
>
> alias ehgrep='awk '\''{for(i=6;i<=NF;i++) printf $i""FS;print ""}'\''
> ~/.bash_eternal_history | awk '\''!a[$0]++'\''|grep -E --color '

Thanks, but when I using this one I meet the following issue:

werner@debian-01:~$ ehgrep awk
awk: cmd. line:1: (FILENAME=/home/werner/.bash_eternal_history FNR=102)
fatal: not enough arguments to satisfy format string
`-I%s '
^ ran out for this one
[...]

The 102nd line of the file is as follows:

werner@debian-01:~$ head -102 /home/werner/.bash_eternal_history |tail -1
4871 werner 1928 [2016-01-21 14:53:06] date -I%s

Hongyi Zhao

unread,
Jan 21, 2016, 5:47:44 AM1/21/16
to
On Thu, 21 Jan 2016 03:27:24 -0500, Chris F.A. Johnson wrote:

> man bash:
> "For almost every purpose, aliases are superseded by shell functions."

Thanks, implemented as follows:

function ehg(){ awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "$@" ; }

Then using it meet the following issues:

$ ehg awk
awk: cmd. line:1: (FILENAME=/home/werner/.bash_eternal_history FNR=102)
fatal: not enough arguments to satisfy format string
`-I%s '
^ ran out for this one

[...]

How to solve this issue?

Rakesh Sharma

unread,
Jan 21, 2016, 6:45:08 AM1/21/16
to
hints:
what is $i doing in awk code?
look up the syntax of the "printf" function of awk. you have missing comma.

BTW, what are you thinking of doing with an incomplete grep command?

You must first ensure all the components of alias that you"re trying to write
can stand on their own. Your's dont. Once you clean up those, then you are sure
that any errors that you face are due to alias. As things stand in your case,
it isn't sure whether it is the alias that is creating them or the commands themselves :-\

Hongyi Zhao

unread,
Jan 21, 2016, 8:36:47 AM1/21/16
to
On Thu, 21 Jan 2016 03:44:55 -0800, Rakesh Sharma wrote:

> hints:
> what is $i doing in awk code?
> look up the syntax of the "printf" function of awk. you have missing
> comma.

Got it. Thanks a lot. Now, I use the function for this thing as follows:

function ehg(){ awk '{for(i=6;i<=NF;i++) printf "%s", $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "$@" ; }

>
> BTW, what are you thinking of doing with an incomplete grep command?

The arguments feeding to grep are should be the the ones given to the
alias-command / customized-function defined by me.

The more readable way should be using the function, so I switched to
customized-function for this case.

>
> You must first ensure all the components of alias that you"re trying to
> write can stand on their own. Your's dont. Once you clean up those, then
> you are sure that any errors that you face are due to alias. As things
> stand in your case,
> it isn't sure whether it is the alias that is creating them or the
> commands themselves :-\

I still cann't understand your above notes clearly.

Hongyi Zhao

unread,
Jan 21, 2016, 8:38:15 AM1/21/16
to
On Thu, 21 Jan 2016 10:44:54 +0000, Hongyi Zhao wrote:

> function ehg(){ awk '{for(i=6;i<=NF;i++) printf $i""FS;print ""}'
> ~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "$@" ; }

Should b used as follows:

function ehg(){ awk '{for(i=6;i<=NF;i++) printf "%s", $i""FS;print ""}'
~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color "$@" ; }

Thanks again.
>
> Then using it meet the following issues:

Kaz Kylheku

unread,
Jan 21, 2016, 9:04:33 AM1/21/16
to
On 2016-01-21, Hongyi Zhao <hongy...@gmail.com> wrote:
> Hi all,
>
> I want to define the following alias:
>
> alias ehgrep='awk '

That's a complete alias.

> ... {for(i=6;i<=NF;i++) printf $i""FS;print ""}'
> ~/.bash_eternal_history | awk '!a[$0]++'|grep -E --color '

That is trailing junk.

Joerg.S...@fokus.fraunhofer.de

unread,
Jan 25, 2016, 9:33:16 AM1/25/16
to
In article <cch6nc-...@chris.tor>,
Chris F.A. Johnson <newsg...@cfaj.ca> wrote:
>On 2016-01-21, Hongyi Zhao wrote:
>> Hi all,
>>
>> I want to define the following alias:
>
>man bash:
> "For almost every purpose, aliases are superseded by shell functions."

This is just a man page from a shell that does not implement a method to
support parameterized macros.

Shell functions have the pitfall that they are listed when you call "set".

Modern versions of the Bourne Shell include a builtin command called "dosh"
that allows to implement one-line shell scripts with an own set of $* ($@)
parameters. The concept is from the "UNOS" command shell from 1980.

You could e.g. have a "lm" alias that expands to:

dosh 'ls -l "$@" | more' lm

and then e.g. type:

lm *.c

The advantage of this concept is that you only have definitions in the cleanly
separated alias namespace and that the parameterization is implemented via a
single builtin program instead via one specific shell function.

--
EMail:jo...@schily.net (home) Jörg Schilling D-13353 Berlin
joerg.s...@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/

Kaz Kylheku

unread,
Jan 25, 2016, 12:04:27 PM1/25/16
to
On 2016-01-25, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:
> In article <cch6nc-...@chris.tor>,
> Chris F.A. Johnson <newsg...@cfaj.ca> wrote:
>>On 2016-01-21, Hongyi Zhao wrote:
>>> Hi all,
>>>
>>> I want to define the following alias:
>>
>>man bash:
>> "For almost every purpose, aliases are superseded by shell functions."
>
> This is just a man page from a shell that does not implement a method to
> support parameterized macros.
>
> Shell functions have the pitfall that they are listed when you call "set".

This is somewhat of a misfeature of "set". The shell effectively has two
namespaces, like Common Lisp. You can have a function called foo, and a
variable called foo. Yet, "set" spews both namespaces.

What is worse, though, is that "unset" removes from both---but one at a
time (at least in Bash).

> Modern versions of the Bourne Shell include a builtin command called "dosh"
> that allows to implement one-line shell scripts with an own set of $* ($@)
> parameters. The concept is from the "UNOS" command shell from 1980.
>
> You could e.g. have a "lm" alias that expands to:
>
> dosh 'ls -l "$@" | more' lm
>
> and then e.g. type:
>
> lm *.c

This doesn't seem like progress over:

$ lm() { ls -l "$@" | more; }
$ lm *.c

> The advantage of this concept is that you only have definitions in the
> cleanly separated alias namespace

It isn't entirely separated, because a symbol in the leftmost position
of the command line could potentially be a function or alias (or builtin
or external). So at dispatch time, at least, the two namespaces
come together. If foo is both an alias an a function, the shell has to
work out which is invoked by "foo arg ...".

The problem with "set" you describe could be fixed by providing
alternative commands for listing the namespaces, and for unbinding
functions and variables.

For instance "lsvar" could list variables, "lsfun" could list functions,
"unbind x" could remove variable x (like Lisp's makunbound), "funbind x"
could remove function x.

Bash has solved this problem with options on "unset":

unset -v foo # unset in variable namespace
unset -f foo # unset in function namespace

The fact that set lists everything is moot; nobody ever does that
other than interactively.

Bringing in yet another namespace just because "set" doesn't work the
way you want seems really a poor design approach. Fix or replace that
which is broken, directly.

> implemented via a
> single builtin program instead via one specific shell function.

What does that mean and why would anyone care?

If you write multiple shell functions, they are dispatched and
interpreted through the same built-in mechanism.

If you write multiple dosh aliases, same thing: multiple definitions
are dispatched through the same dosh-alias-dispatching mechanism.

Kaz Kylheku

unread,
Jan 25, 2016, 12:49:10 PM1/25/16
to
On 2016-01-25, Kaz Kylheku <609-57...@kylheku.com> wrote:
> On 2016-01-25, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:
> Bash has solved this problem with options on "unset":
>
> unset -v foo # unset in variable namespace
> unset -f foo # unset in function namespace

Oops, spoke too soon---this is a POSIX feature!

So, what issues remain in the POSIX command language w.r.t. the
"unclean" separation of namespaces, other than that "set" lists both of
them?

Functions and variables are created using different syntax, so the spaces
are distinguished at binding time.

The use of these identifiers is distinguished syntactically; there
isn't ever a question of whether a reference to foo is to a function
or variable, except when -f and -v are not used in the "unset" command,
when it becomes unspecified whether a function or variable is removed.

Joerg.S...@fokus.fraunhofer.de

unread,
Jan 26, 2016, 11:24:30 AM1/26/16
to
In article <201601250...@kylheku.com>,
Kaz Kylheku <609-57...@kylheku.com> wrote:
>On 2016-01-25, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:
>> In article <cch6nc-...@chris.tor>,

>> Shell functions have the pitfall that they are listed when you call "set".
>
>This is somewhat of a misfeature of "set". The shell effectively has two
>namespaces, like Common Lisp. You can have a function called foo, and a
>variable called foo. Yet, "set" spews both namespaces.

No, the Bourne Shell and POSIX document shell parameters and shell functions to
be in the same namespace.

>What is worse, though, is that "unset" removes from both---but one at a
>time (at least in Bash).

This is not POSIX.

POSIX explains that a function and a shell parameter of the same name are
impossible. POSIX also allows to avoid to unset a parameter (variable) by
calling "unsef -f name".


>> Modern versions of the Bourne Shell include a builtin command called "dosh"
>> that allows to implement one-line shell scripts with an own set of $* ($@)
>> parameters. The concept is from the "UNOS" command shell from 1980.
>>
>> You could e.g. have a "lm" alias that expands to:
>>
>> dosh 'ls -l "$@" | more' lm
>>
>> and then e.g. type:
>>
>> lm *.c
>
>This doesn't seem like progress over:
>
> $ lm() { ls -l "$@" | more; }
> $ lm *.c

It is because of the name space I mentioned.

>> The advantage of this concept is that you only have definitions in the
>> cleanly separated alias namespace
>
>It isn't entirely separated, because a symbol in the leftmost position
>of the command line could potentially be a function or alias (or builtin
>or external). So at dispatch time, at least, the two namespaces
>come together. If foo is both an alias an a function, the shell has to
>work out which is invoked by "foo arg ...".

You are missinterpreting name spaces.

Aliases are identified and replaced in the lexer part of the parser.

The lexer identified a word, looks it up in the alias name space and if there
is a match, it pushes the replacement and rescans the input.

Functions on the other side are recognised in the interpreter much later in the
shell dataflow.

>The fact that set lists everything is moot; nobody ever does that
>other than interactively.

No, this is a result of the fact that parameter name space and function
namespace are not separate.


>> implemented via a
>> single builtin program instead via one specific shell function.
>
>What does that mean and why would anyone care?

Because of the variable name space pollution caused by functions.

>If you write multiple shell functions, they are dispatched and
>interpreted through the same built-in mechanism.
>
>If you write multiple dosh aliases, same thing: multiple definitions
>are dispatched through the same dosh-alias-dispatching mechanism.


As explained, the alias -> dosh '...' arg0-name method uses fewer resources and
does not pollute the name spaces.

Kaz Kylheku

unread,
Jan 26, 2016, 12:08:36 PM1/26/16
to
On 2016-01-26, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:
> In article <201601250...@kylheku.com>,
> Kaz Kylheku <609-57...@kylheku.com> wrote:
>>On 2016-01-25, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:
>>> In article <cch6nc-...@chris.tor>,
>
>>> Shell functions have the pitfall that they are listed when you call "set".
>>
>>This is somewhat of a misfeature of "set". The shell effectively has two
>>namespaces, like Common Lisp. You can have a function called foo, and a
>>variable called foo. Yet, "set" spews both namespaces.
>
> No, the Bourne Shell and POSIX document shell parameters and shell
> functions to be in the same namespace.
>
> [ ... ]
>
> POSIX explains that a function and a shell parameter of the same name
> are impossible.

Good grief!

I don't know what POSIX you're looking at.

The Open Group Base Specifications Issue 7 IEEE Std 1003.1™, 2013
Edition, Online, "Shell Command Language":

2.9.5 Function Definition Command

[ ... ]

The implementation shall maintain separate name spaces for functions
and variables.

URL: <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_05>

>>If you write multiple shell functions, they are dispatched and
>>interpreted through the same built-in mechanism.
>>
>>If you write multiple dosh aliases, same thing: multiple definitions
>>are dispatched through the same dosh-alias-dispatching mechanism.
>
> As explained, the alias -> dosh '...' arg0-name method uses fewer
> resources and does not pollute the name spaces.

You can fit a file on every citizen of the US onto a micro SD card,
and read it on your cell phone.

Someone would have to create a million dosh aliases or functions before
anything noteworthy even begins to show up on the process monitor.

Nobody in their right mind worries about the resources of a "dosh"
definition versus a function, and wouldn't have worried about this
as far back as at least 1996. Your concerns belong to a bygone era.

Plus, your statement is not believable without proper analysis. There
are ways to implement both these features with varying time/space
tradeoffs.

Dosh absolutely polutes namespaces. Firstly it pollutes the
meta-namespace: the top level environment which contains namespaces. It
pollutes it by adding yet a new namespace. Secondly, that namespace
conflates with the other command namespaces. If we have a "foo bar"
command, foo can potentially be a dosh alias or a function, among
other things. If both a function and a dosh are defined, that either
must be disallowed, or resolved somehow: one hides the other according
to some rule. This adds complexity. On top of that, aliases are POSIX,
so you can't just get rid of *those* if you want conformance. There is
already enough of a mess there: the leftmost word of a command could be
a builtin, an external utility in the PATH, a function or an alias.
More cruft is not needed.

Joerg.S...@fokus.fraunhofer.de

unread,
Jan 27, 2016, 5:03:44 AM1/27/16
to
In article <201601260...@kylheku.com>,
Kaz Kylheku <609-57...@kylheku.com> wrote:
>On 2016-01-26, Joerg.S...@fokus.fraunhofer.de <Joerg.S...@fokus.fraunhofer.de> wrote:

>The Open Group Base Specifications Issue 7 IEEE Std 1003.1â„¢, 2013
>Edition, Online, "Shell Command Language":
>
> 2.9.5 Function Definition Command
>
> [ ... ]
>
> The implementation shall maintain separate name spaces for functions
> and variables.
>
> URL: <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_05>

Interesting catch and it seems that this really applies to the certified
special ksh88 that is the base for POSIX.

>> As explained, the alias -> dosh '...' arg0-name method uses fewer
>> resources and does not pollute the name spaces.
>
>You can fit a file on every citizen of the US onto a micro SD card,
>and read it on your cell phone.

This does not look like an argument.

>Dosh absolutely polutes namespaces. Firstly it pollutes the
>meta-namespace: the top level environment which contains namespaces. It

Sorry, but you would first need to understand this mechanism before you start
to critizise it.

Your claims to not apply.

The "dosh" builtin is just a generic template for a generic built in one-line
shell script.

A function definition is however always specific.

Geoff Clare

unread,
Jan 27, 2016, 8:41:11 AM1/27/16
to
Kaz Kylheku wrote:

> So, what issues remain in the POSIX command language w.r.t. the
> "unclean" separation of namespaces, other than that "set" lists both of
> them?

POSIX requires that "set" lists shell variables. Shells which also
list functions do not conform to POSIX. Note that although bash lists
functions by default, it does not list them when executed in POSIX mode.

--
Geoff Clare <net...@gclare.org.uk>

Joerg.S...@fokus.fraunhofer.de

unread,
Jan 27, 2016, 9:14:24 AM1/27/16
to
In article <hvtmnc-...@ID-313840.user.individual.net>,
Geoff Clare <net...@gclare.org.uk> wrote:

>POSIX requires that "set" lists shell variables. Shells which also
>list functions do not conform to POSIX. Note that although bash lists
>functions by default, it does not list them when executed in POSIX mode.

It seems that you identified a problem:

There is no POSIX command to list all functions, isn't it?

ksh implements the "typeset" builtin, but this is not part of POSIX.

Geoff Clare

unread,
Jan 28, 2016, 8:41:08 AM1/28/16
to
Joerg.Schilling wrote:

> In article <hvtmnc-...@ID-313840.user.individual.net>,
> Geoff Clare <net...@gclare.org.uk> wrote:
>
>>POSIX requires that "set" lists shell variables. Shells which also
>>list functions do not conform to POSIX. Note that although bash lists
>>functions by default, it does not list them when executed in POSIX mode.
>
> It seems that you identified a problem:
>
> There is no POSIX command to list all functions, isn't it?

True, but that's not something I've ever felt the need to do.

--
Geoff Clare <net...@gclare.org.uk>

Kaz Kylheku

unread,
Jan 28, 2016, 1:07:26 PM1/28/16
to
Interesting; on the other hand, I have done it numerous times in Bash
(interactively) to confirm that certain functions are loaded, and glance
what is in them.

Stephane Chazelas

unread,
Jan 29, 2016, 5:40:14 AM1/29/16
to
2016-01-28 18:07:18 +0000, Kaz Kylheku:
[...]
> >> There is no POSIX command to list all functions, isn't it?
> >
> > True, but that's not something I've ever felt the need to do.
>
> Interesting; on the other hand, I have done it numerous times in Bash
> (interactively) to confirm that certain functions are loaded, and glance
> what is in them.

For that, you can use "type".

Note that POSIX's main point is to specify a portable
programming API.

--
Stephane

Joerg.S...@fokus.fraunhofer.de

unread,
Jan 29, 2016, 6:46:38 AM1/29/16
to
In article <201601281...@kylheku.com>,
If you know the name of a possible function, POSIX allows you to verify whether
there is a function, but it does not give you a command to list the function
definition.

This is because neither the "type" command from the Bourne Shell nor the
"typeset" command from ksh are part of POSIX.

What POSIX permits you to do is to call "command -V name" and verify that
"name" is connected to a function. The POSIX standard defines that "command -V"
should behave like "type", but it also defines the output format that does not
leave room for printing the function definition, as done by calling "type name".

For this reason, I filed a related bug report against the POSIX standard.
0 new messages