繁体   English   中英

Unix'别名'失败了'awk'命令

[英]Unix 'alias' fails with 'awk' command

我在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;博士

问题是OP尝试使用' 内部 '封闭(单引号)字符串。

在这种情况下, 最健壮的解决方案是替换每个内部 ''\\'' (原文如此):

alias logspace='find /apps/ /opt/ -type f -size +100M -exec ls -lh {} \; | 
                awk '\''{print $5, $9 }'\'''
  • 类似Bourne(POSIX兼容)弹不支持使用' (内单引号字符'...' -enclosed)串在所有-即使不是逃避
    • (相比之下,你能逃脱" -quoted字符串作为内部\\" ,并且,如@ Droput的回答,您可以直接嵌入'字符。在那里,但请参阅下面的陷阱。)
  • 上面的解决方案有效地从多个单引号字符串构建字符串,字符串为'字符”。 - 在单引号字符串之外转义为\\' - 拼接在一起
    另一种表达方式,正如@Etan Reisinger在评论中所做的那样: '\\''表示:“关闭字符串”,“转单引号”,“启动新字符串”。
  • 定义别名时 ,通常需要围绕其定义使用引号 ,以便延迟对命令的评估 ,直到调用别名为止。

其他解决方案及其缺陷

以下讨论基于以下别名的替代解决方案:

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

注意*如何有效地用单引号括起来 - 使用上面的技术 - 以便在以后调用别名时防止路径名扩展。

当被调用时,这个别名打印文字 A * star is born ,然后是当时的日期和时间,例如: A * is born at Mon Jun 16 11:33:19 EDT 2014


使用名为ANSI C引用的功能以及支持它的shell: bashkshzsh

ANSI C引用的字符串, 包含在$'...' ,DO允许转义嵌入的'字符。 作为\\'

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

虽然语法正确的,这将不会按预期进行,因为使用了引号,shell会展开命令替换$(date) 向右走 ,因而硬连线的别名定义成别名时的日期和时间

如上所述:在定义别名时 ,通常需要围绕其定义使用引号 ,以便延迟对命令的评估 ,直到调用别名为止。


最后,一个警告

在一个类似Bourne shell环境的棘手的事情是嵌入'单引号字符串中有时-错误-似乎工作 (而不是产生一个语法错误,因为在这个问题),当它反而就不一样了:

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

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

你可以使用不同的引号来包围整个文本和内部字符串。

尝试将其更改为

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

换句话说,您的外部引号应该与内部引号不同,因此它们不会混合。

社区维基更新

  • 这个答案的可取之处是认识到OP的问题就出在转义使用字符串分隔符(的' )在字符串
  • 然而, 这个答案一般包含字符串处理的真理,但并不适用于(类似Bourne,POSIX兼容)shell编程明确 ,因而不能直接解决了OP的问题-看评论。

注意:代码片段是伪代码 ,而不是shell语言。

基本字符串:您不能在字符串中使用相同的引号,因为整个字符串是用以下分隔的:

foo='hello, 'world!'';
    ^--start string
            ^-- end string
             ^^^^^^^^--- unknown "garbage" causing syntax error.

你必须转义内部字符串:

foo='hello, \'world!\'';
            ^--escape

这对于地球上几乎每种编程语言都是如此。 如果它们不提供转义机制,例如\\ ,则必须使用其他方法,例如

quotechar=chr(39); // single quote is ascii #39
foo='hello ,' & quotechar & 'world!' & quotechar;

转义$符号而不是awk的单引号,并使用双引号作为别名。

试试这个 :

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM