Unix'alias'使用'awk'命令失败 [英] Unix 'alias' fails with 'awk' command

查看:354
本文介绍了Unix'alias'使用'awk'命令失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Unix中创建别名,发现以下命令失败.

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

我得到以下信息:

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

关于为什么管道化awk命令失败的任何想法...

谢谢, 肖恩.

解决方案

以补充 @Dropout的有用答案:

tl; dr

问题是OP尝试在'内(单引号)的字符串中使用' .

在这种情况下,最可靠的解决方案是用'\'' (原文如此)替换每个 interior ':

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

  • 类似Bourne的(兼容POSIX的)shell根本不支持在单引号('...'括起来)的字符串中使用'字符-甚至无法转义.
    • (相反,您可以在 double 引号中的字符串内将"转义为\",就像@Droput的答案一样,您可以直接将'字符嵌入. ,但请参阅下面的陷阱.)
  • 上述解决方案可以有效地从多个单引号字符串中构建字符串,这些字符串将文字'转换为字符. -在外部中转义为\'的单引号字符串-在中拼接 .
    另一种表达方式,如@Etan Reisinger在评论中所做的:'\''表示:关闭字符串",转义单引号",开始新字符串".
  • 定义别名时,通常需要在其定义周围加上 引号,以便延迟评估该命令,直到别名被调用.

其他解决方案及其陷阱:

以下内容基于以下别名讨论了替代解决方案:

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

请注意如何使用上述技术有效地将*括在单引号中,以防止在以后调用别名时扩展路径名.

在调用时,此别名显示 literal A * star is born,后跟 then -当前日期和时间,例如:A * is born at Mon Jun 16 11:33:19 EDT 2014.


使用称为 ANSI C引用具有支持它的shell:bashkshzsh

用ANSI C引号括起来的字符串,该字符串用括在$'...'中,但允许转义嵌入的'字符.为\' :

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

陷阱:

  • 此功能不是POSIX的一部分.
  • 通过设计,还解释了诸如\n\t,...之类的转义序列(实际上,这就是该功能的目的).

使用交替引号样式,如@Dropout的答案:

陷阱:

'...'"..."具有不同的语义,因此用一个替换另一个会产生意想不到的副作用:

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

尽管语法上正确,但这将无法按预期工作,因为使用 double 引号会使外壳程序立即扩展命令替换$(date) ,因此 硬线将别名定义转换为别名时的日期和时间.

如上所述:定义别名时,通常需要在其定义周围加上 引号,以便延迟评估.命令> strong>,直到别名被调用.


最后,是 caveat :

在类似Bourne的shell环境中,棘手的事情是有时将'嵌入在单引号中-错误地-似乎可以正常工作(而不是像问题),那么当它做一些不同的事情时:

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

此定义已被接受(没有语法错误),但无法按预期工作-该定义的右侧被有效地解析为 3 字符串- 'echo a '*' is born at $(date)'(由于外壳如何解析字符串(合并相邻的字符串,删除引号))导致以下文字字符串:.由于在生成的别名定义中*未用引用,因此在调用别名时,它将扩展为当前目录中所有文件/目录名称的列表(路径名扩展).

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.

解决方案

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 \n, \t, ... 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.

这篇关于Unix'alias'使用'awk'命令失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆