You are not logged in.

#1 2021-03-27 08:58:12

Ferdinand
Member
From: Norway
Registered: 2020-01-02
Posts: 338

Bash alias quoting

The usage quotes is covered lots of places on the net, and there has been several questions relating to it in this forum.
Still, I seem to be forever wobbling when making aliases - and assuming I'm not alone; here's yet another quotes question, with the intention of triggering insightful comments and obtain useful recommendations.

To start off...

  • Double quotes expand variables, and single quotes do not, but there are peculiarities. E.g. echo ~ expands to /home/user, echo '~' does not expand, and curiously, neither do echo "~".

  • The alias command prefers single quotes. E.g. alias tezt="echo '~'" and then alias tezt produces alias tezt='echo '\''~'\''' (that's all single quotes).

What do you do when making alias; enclosing in single or double quotes? And what do you do when nesting quotes within quotes? And why?

Is this

alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'

better than

alias colourlist="cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '{print \$4}' | grep '\S' | sort -u"

or should we use functions more? Do you have better or more enlightening examples than what I gave here?

Offline

#2 2021-03-27 17:43:27

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,426
Website

Re: Bash alias quoting

The first step is to remove all the bloat from the awk invocation:

awk '$2~/^[0-9]/{print $4}' /usr/share/netpbm/rgb.txt

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#3 2021-03-27 18:17:05

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,507
Website

Re: Bash alias quoting

Also your `grep "\S"` is not doing what you think it's doing.  Is it your intent to remove color names with spaces?  If so, the space is already gone when you print (just) the fourth column.  Then on top of that \S matches anything that is not a space (I think that's what it's for right, that seems to be the resulting behavior) - which will still match lines with a space so long as there is at least one character that is not a space.  Perhaps you intended that to be `grep -v "\s"` or `grep '^\S*$`, but still the first issue remains.

Of course, none of that addresses your question about quotes - but it's kinda' a moot point: quoting is hard when your commands are needlessly complex; so don't make your commands needlessly complex.

If you don't want to chop off the second part of color names with spaces, don't use awk, try sed (and be forewarned that the file in question has a very odd and inconsistent mix of spaces and tabs ... I gather it was assembled from multiple sources and not cleaned):

sed -n 's/[0-9 \t]\{11\} *//p' /usr/share/netpbm/rgb.txt | sort -u

Or perhaps a more future proof version would use awk, but not assume the 4th column was the full color name (which also does the sort -u for you):

awk '$1~/^[0-9]/{$1=$2=$3=""; sub(/^ */,"",$0); col[$0]=1;} END{for(c in col) print c;}' /usr/share/netpbm/rgb.txt

And would I use single or double quotes when I made an alias out of that?  Hard to say, as I'd never make an alias out of that!

Last edited by Trilby (2021-03-27 18:22:40)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#4 2021-03-27 19:17:46

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,599

Re: Bash alias quoting

Aliases are not meant to do that they are to replace lengthy commands, something like a long qemu or ssh command. not one-liners.
You already noticed this in your alias because you needed to escape the arguments '\$4' etc.
I wouldn't even try to create an alias of the sed & awk one-liners Trilby posted.
You asked if you should use functions, yes you should they are made for this task and is the preferred way!

Offline

#5 2021-03-27 20:35:13

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,507
Website

Re: Bash alias quoting

qinohe wrote:

I wouldn't even try to create an alias of the sed & awk one-liners Trilby posted.

It's pretty easy to do, just pointless:

alias worthlesscommand='sed -n "s/[0-9 \t]\{11\} *//p" /usr/share/netpbm/rgb.txt | sort -u'

"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#6 2021-03-27 21:00:58

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,599

Re: Bash alias quoting

Yes, that one works, I haven't tried the awk one, though, I'm sure you need to adjust it for it won't work as it is now.
Still, aliases are not meant to be used in that manner even though you can, mostly.

Try this one-liner and make it a alias, while it works fine as function, it will diverge so much from the one you use in the shell, why should you?

xev | awk -F"[ )]+" '/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", $5, $8 }'

Offline

#7 2021-03-27 22:04:25

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,507
Website

Re: Bash alias quoting

You only need to adjust the quoting around the awk script:

alias crap='xev | awk -F"[ )]+" '\''/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", $5, $8 }'\'''

Last edited by Trilby (2021-03-27 22:04:55)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#8 2021-03-28 11:23:31

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,599

Re: Bash alias quoting

There's is indeed less tweak needed than I expected!
When I started using aliases -ages ago- I looked up it's conditions and thus I would never put these small scripts in an alias but a function.
I looked up the bash part of the manual about aliases (see) https://www.gnu.org/software/bash/manua … iases.html

Offline

#9 2021-04-03 17:29:22

Ferdinand
Member
From: Norway
Registered: 2020-01-02
Posts: 338

Re: Bash alias quoting

Thank you for the killer aliases big_smile

I understand what you say, I also acknowledge that you are much more skilled than me in this, and I enjoy learning from you - and I note that the Bash manual indeed states that For almost every purpose, shell functions are preferred over aliases..

I'm inclined to be a little bit stubborn on this though, as I think functions tend to "disappear" from view; how would you go about listing all the functions you have defined (as with aliases)?
Something like

alias functions='set | awk '\''!/^[[:space:]]/ && /\(/ && !/=/'\'''

includes functions from wherever else. And in order to include aliases, something like this would be required... mad

alias alias='printf "Functions:\n";set | awk '\''!/^[[:space:]]/ && /\(/ && !/=/'\'';printf "\nAliases:\n";alias'

It will still add aliases, but the output on creation will eh.. change a bit roll (so, maybe that should be a function)

In short, I kind of like to alias my on-liners tongue

Anyway - to return to the OP - I think it's fair to say that aliases should be defined with single quotes, simply because that's how alias writes them back:

$ alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'
$ alias | grep colourlist
alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'
$ alias colourlist="cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '{print \$4}' | grep '\S' | sort -u"
$ alias | grep colourlist
alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '\''{print $4}'\'' | grep '\''\S'\'' | sort -u'

That was my bit...

Offline

#10 2021-04-03 17:44:46

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,507
Website

Re: Bash alias quoting

I'm not sure what those first two code blocks were intended to do.  Do you want to list aliases defined in the current environment?  Just use the command `alias` with no arguments and they'll all be listed (as long as you don't alias alias, which is a horrible idea for many reasons).  If you want a listing of all functions in bash, `typeset -f` or `declare -f` (both of these are bashisms that I don't really know the difference between).

Last edited by Trilby (2021-04-03 17:47:55)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#11 2021-04-03 19:22:22

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,599

Re: Bash alias quoting

Trilby wrote:

both of these are bashisms that I don't really know the difference between.

According to the manual typeset is portable declare isn't.
They are synonymous though, (see) https://www.gnu.org/software/bash/manua … h-Builtins

Offline

#12 2021-04-03 19:30:14

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,599

Re: Bash alias quoting

Ferdinand wrote:

...
I'm inclined to be a little bit stubborn on this though
...

No one here is holding you back, you're simply provided with info on the way it's supposed to be used, and you asked for it tongue

Offline

#13 2021-04-03 19:32:05

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,426
Website

Re: Bash alias quoting

Ferdinand wrote:
$ alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'

Good to see that, 9 posts later, you still have a useless use of cat, two redundant greps, and managed to completely ignore everything anyone else has posted...


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#14 2021-04-03 21:39:27

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,507
Website

Re: Bash alias quoting

jasonwryan wrote:

... you still have ... managed to completely ignore everything anyone else has posted...

He owned it:

Ferdinand wrote:

I'm inclined to be a little bit stubborn

tongue


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#15 2021-04-07 05:04:56

eschwartz
Fellow
Registered: 2014-08-08
Posts: 4,097

Re: Bash alias quoting

Ferdinand wrote:

Thank you for the killer aliases big_smile

I understand what you say, I also acknowledge that you are much more skilled than me in this, and I enjoy learning from you - and I note that the Bash manual indeed states that For almost every purpose, shell functions are preferred over aliases..

Correct, the opinion of many is that aliases were a mistake. And truthfully, there is nothing an alias can do that a function cannot do, other than weird macro preprocessor in-place line editing of your command which you should not be doing. Interesting reading: https://www.chiark.greenend.org.uk/~sgt … iases.html

Guess what aliases cannot do, which functions can do?

They cannot be written sanely without stuffing code into a string. Painful quoting/escaping contortions are needed for complex aliases, but functions completely sidestep this. It's the same reason why "eval" is a common misspelling of "evil".

Ferdinand wrote:

I'm inclined to be a little bit stubborn on this though, as I think functions tend to "disappear" from view; how would you go about listing all the functions you have defined (as with aliases)?

compgen -A function (or declare -F if you want to get each function name prefixed by "declare -f")

Ferdinand wrote:

Something like

alias functions='set | awk '\''!/^[[:space:]]/ && /\(/ && !/=/'\'''

includes functions from wherever else.

Huh? set doesn't print any functions at all. Or better, it might or might not print any functions at all.

Ferdinand wrote:

And in order to include aliases, something like this would be required... mad

alias alias='printf "Functions:\n";set | awk '\''!/^[[:space:]]/ && /\(/ && !/=/'\'';printf "\nAliases:\n";alias'

It will still add aliases, but the output on creation will eh.. change a bit roll (so, maybe that should be a function)

What is the point of this? Incidentally, if you try adding an alias, the additional output you just introduced, will report zero aliases. You need to guarantee 'alias' runs once without arguments, but not run it twice if the second time would have no arguments...

Ferdinand wrote:

In short, I kind of like to alias my on-liners tongue

Create the philosophical concept of an alias, using the technical concept of a function.

Ferdinand wrote:

Anyway - to return to the OP - I think it's fair to say that aliases should be defined with single quotes, simply because that's how alias writes them back:

This betrays a grave misunderstanding of the concept of shell quoting.

Use the power of word splitting, and the corollary power of word splitting suppression through the mechanism of single quotes, double quotes, or backslash escapes... in order to build up an array of shell words passed to the "alias" builtin. Do not permit petty limitations like "single quote everything" to stand in your way in cases where you need single quotes in the command to run.

Do not permit petty limitations like "the shell machine-parseable printer happens to format it this way" to stand in your way either. The output of "alias" is documented as suitable for reuse, it in no way recommends that as the exclusive good practice methodology. Don't build a religion based on superstitions about bash printing it like this meaning it's "better".

Ferdinand wrote:
$ alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'
$ alias | grep colourlist
alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk "{print \$4}" | grep "\S" | sort -u'
$ alias colourlist="cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '{print \$4}' | grep '\S' | sort -u"
$ alias | grep colourlist
alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '\''{print $4}'\'' | grep '\''\S'\'' | sort -u'

That was my bit...

$ alias colourlist="cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '{print \$4}' | grep '\S' | sort -u"
$ alias colourlist
alias colourlist='cat /usr/share/netpbm/rgb.txt | grep -v \# | awk '\''{print $4}'\'' | grep '\''\S'\'' | sort -u'

Why are you GREPPING the output of the alias builtin?


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

Board footer

Powered by FluxBB