Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm creating an alias in Unix and have found that the following command fails..

alias logspace='find /apps/ /opt/ -type f -size +100M -exec ls -lh {} ; | awk '{print $5, $9 }''

I get the following :

awk: cmd. line:1: {print
awk: cmd. line:1:       ^ unexpected newline or end of string

Any ideas on why the piped awk command fails...

Thanks, Shaun.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
557 views
Welcome To Ask or Share your Answers For Others

1 Answer

To complement's @Dropout's helpful answer:

tl;dr

The problem is the OP's attempt to use ' inside a '-enclosed (single-quoted) string.

The most robust solution in this case is to replace each interior ' with ''' (sic):

alias logspace='find /apps/ /opt/ -type f -size +100M -exec ls -lh {} ; | 
                awk '''{print $5, $9 }''''
  • Bourne-like (POSIX-compatible) shells do not support using ' chars inside single-quoted ('...'-enclosed) strings AT ALL - not even with escaping.
    • (By contrast, you CAN escape " inside a double-quoted string as ", and, as in @Droput's answer, you can directly, embed ' chars. there, but see below for pitfalls.)
  • The solution above effectively builds the string from multiple, single-quoted strings into which literal ' chars. - escaped outside the single-quoted strings as ' - are spliced in.
    Another way of putting it, as @Etan Reisinger has done in a comment: ''' means: "close string", "escape single quote", "start new string".
  • When defining an alias, you usually want single quotes around its definition so as to delay evaluation of the command until the alias is invoked.

Other solutions and their pitfalls:

The following discusses alternative solutions, based on the following alias:

alias foo='echo A '''*''' is born at $(date)'

Note how the * is effectively enclosed in single quotes - using above technique - so as to prevent pathname expansion when the alias is invoked later.

When invoked, this alias prints literal A * star is born, followed by the then-current date and time, e.g.: A * is born at Mon Jun 16 11:33:19 EDT 2014.


Use a feature called ANSI C quoting with shells that support it: bash, ksh, zsh

ANSI C-quoted strings, which are enclosed in $'...', DO allow escaping embedded ' chars. as ':

alias foo=$'echo A '*' is born at $(date)'

Pitfalls:

  • This feature is not part of POSIX.
  • By design, escape sequences such as , , ... are interpreted, too (in fact, that's the purpose of the feature).

Use of alternating quoting styles, as in @Dropout's answer:

Pitfall:

'...' and "..." have different semantics, so substituting one for the other can have unintended side-effects:

alias foo="echo A '*' is born at $(date)" # DOES NOT WORK AS INTENDED

While syntactically correct, this will NOT work as intended, because the use of double quotes causes the shell to expand the command substitution $(date) right away, and thus hardwires the date and time at the time of the alias definition into the alias.

As stated: When defining an alias, you usually want single quotes around its definition so as to delay evaluation of the command until the alias is invoked.


Finally, a caveat:

The tricky thing in a Bourne-like shell environment is that embedding ' inside a single-quoted string sometimes - falsely - APPEARS to work (instead of generating a syntax error, as in the question), when it instead does something different:

 alias foo='echo a '*' is born at $(date)'  # DOES NOT WORK AS EXPECTED.

This definition is accepted (no syntax error), but won't work as expected - the right-hand side of the definition is effectively parsed as 3 strings - 'echo a ', *, and ' is born at $(date)', which, due to how the shell parses string (merging adjacent strings, quote removal), results in the following, single, literal string: a * is born at $(date). Since the * is unquoted in the resulting alias definition, it will expand to a list of all file/directory names in the current directory (pathname expansion) when the alias is invoked.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...