我正在尝试创建一个ll
带有awk
管道别名。我试图使用以下内容来转义撇号答案。
alias lh= `ll -h | awk {'print $9, \"-\" ,$5, \"-\", $8, \"-\",$7, $6'}`
但它似乎不起作用。
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
进入时
alias lh= `ll -h | awk {'print $9, "-" ,$5, "-", $8, "-",$7, $6'}`
输出意味着空。
答案1
您的别名定义存在几个语法问题。然而,第一个问题是解析输出ls
强烈劝阻因为涉及它的代码最终会偶然发现带有“非平凡”字符(例如空格、制表符和换行符)的文件。此外,特别是时间戳的输出格式可能会根据文件实际的“旧”程度而变化,这意味着您可以在输入中包含更多或更少的空格分隔“字段”,具体awk
取决于实际文件,或者一个字段的含义发生变化(例如,从“旧文件”的年份到“最近的文件”的一天中的时间)。这两个方面就是@steeldriver所说的别名“脆弱”。
“明显”的问题是:
- 后面有一个空格
=
。这实际上会使别名lh
未定义(至少在bash
)。 - 您将别名定义括在反引号 (
`
) 中,可能是为了创建“第三层”引用。但是,反引号是命令替换的语法(尽管现在已弃用),即lh
包含ll | awk ...
管道的控制台输出并尝试执行那作为命令。 ll
您依赖于存在或至少预定义为 的别名的命令ls -l
。情况可能是这样,也可能不是。- 您的
awk
程序启动时单引号和大括号的顺序错误。正确的语法是awk ' { ... } '
.
请注意,如果这是 shell 脚本的一部分,您可能需要通过以下方式运行它shellcheck
,也可在许多 Linux 发行版上作为独立工具使用,以捕获许多与语法相关的错误。
您遇到的问题的直接解决方案确实是正确的引用和转义。你可以尝试类似的东西
alias lh="ls -lh | awk '{print \$9, \"-\" ,\$5, \"-\", \$8, \"-\",\$7, \$6}'"
其中别名是 中的所有内容" ... "
, 的输入awk
明确声明为ls -lh
,awk
程序用单引号括起来,并且程序内的字段引用awk
受到保护,以免在“别名的定义时”过早解释为 shell 位置参数反斜杠转义(因此awk
实际上将它们视为$9
而不是被 shell 实例的第 9 个位置参数替换,该参数可能为空)。
然而
中找到的建议您链接的问题的答案之一- 定义一个函数 - 是摆脱“引用地狱”的更好方法(正如@ilkkachu提到的),所以像
lh() { ls -lh | awk '{print $9, "-" ,$5, "-", $8, "-",$7, $6}'; }
更清晰、更容易理解
我建议
ls
完全避免解析,并建议使用以下find
基于别名:lh() { find . -maxdepth 1 -type f ! -name ".*" -printf "%f - %s - %TY - %Td %Tb\n"; }
它使用 的
printf
格式化选项来find
可靠地输出所需的文件属性。唯一的缺点是没有-h
人类可读的尺寸选项。该
! -name ".*"
过滤器用于模拟ls
忽略隐藏文件的标准行为。如果您希望列出它们,则可以省略该部分。