别名管道输入 awk

zer*_*rus 2 bash zsh alias

我正在尝试创建一个ll带有awk管道别名。我试图使用以下答案来逃避撇号。

alias lh= `ll -h | awk {'print  $9, \"-\" ,$5, \"-\", $8, \"-\",$7, $6'}` 
Run Code Online (Sandbox Code Playgroud)

但它似乎不起作用。

bash和 的控制台输出结果zsh是相同的。


awk: cmd. line:1: {print  $9, \"-\" ,$5, \"-\", $8, \"-\",$7, $6}
awk: cmd. line:1:             ^ backslash not last character on line
awk: cmd. line:1: {print  $9, \"-\" ,$5, \"-\", $8, \"-\",$7, $6}
awk: cmd. line:1:             ^ syntax error
Run Code Online (Sandbox Code Playgroud)

进入时

alias lh= `ll -h | awk {'print  $9, "-" ,$5, "-", $8, "-",$7, $6'}`
Run Code Online (Sandbox Code Playgroud)

输出 意味着空。

Adm*_*Bee 8

您的别名定义存在几个语法问题。ls 然而,第一个问题是强烈建议不要解析 的输出,因为涉及它的代码最终会偶然发现带有“非平凡”字符(例如空格、制表符和换行符)的文件。此外,特别是时间戳的输出格式可能会根据文件实际的“旧”程度而变化,这意味着您可以在输入中包含更多或更少的空格分隔“字段”,具体取决于awk实际文件,或者一个字段的含义发生变化(例如,从“旧文件”的年份到“最近的文件”的一天中的时间)。这两个方面就是@steeldriver所说的别名“脆弱”。

“明显”的问题是:

  1. 后面有一个空格=。这实际上会使别名lh未定义(至少在bash)。
  2. 您将别名定义括在反引号 ( `) 中,可能是试图创建“第三层”引用。然而,反引号是命令替换的语法(尽管现在已弃用),即lh包含管道的控制台输出并尝试将ll | awk ...作为命令执行。
  3. ll您依赖于存在或至少预定义为 的别名的命令ls -l。情况可能是这样,也可能不是。
  4. 您的awk程序启动时单引号和大括号的顺序错误。正确的语法是awk ' { ... } '.

请注意,如果这是 shell 脚本的一部分,您可能需要通过 来运行它(shellcheck在许多 Linux 发行版上也可以作为独立工具使用),以捕获许多与语法相关的错误。

您遇到的问题的直接解决方案确实是正确的引用和转义。你可以尝试类似的东西

alias lh="ls -lh | awk '{print  \$9, \"-\" ,\$5, \"-\", \$8, \"-\",\$7, \$6}'"
Run Code Online (Sandbox Code Playgroud)

其中别名是 中的所有内容" ... ", 的输入awk明确声明为ls -lhawk程序用单引号括起来,并且程序内的字段引用awk受到保护,以免在“别名的定义时”过早解释为 shell 位置参数反斜杠转义(因此awk实际上将它们视为$9而不是被 shell 实例的第 9 个位置参数替换,该参数可能为空)。

然而

  • 在您链接的问题的答案之一中找到的建议- 定义一个函数 - 是摆脱“引用地狱”(如@ilkkachu所述)的更好方法,所以类似

    lh() { ls -lh | awk '{print  $9, "-" ,$5, "-", $8, "-",$7, $6}'; }
    
    Run Code Online (Sandbox Code Playgroud)

    更清晰、更容易理解

  • 我建议ls完全避免解析,并建议使用以下find基于别名:

    lh() { find . -maxdepth 1 -type f ! -name ".*" -printf "%f - %s - %TY - %Td %Tb\n"; }
    
    Run Code Online (Sandbox Code Playgroud)

    它使用 的printf格式化选项来find可靠地输出所需的文件属性。唯一的缺点是没有-h人类可读的尺寸选项。

    ! -name ".*"过滤器用于模拟ls忽略隐藏文件的标准行为。如果您希望列出它们,则可以省略该部分。