在 Shell 中提取输出

在 Shell 中提取输出

当我在做的时候

ls -la |grep -e Aug

我得到的输出为

-rw-r--r--    1 root           staff   454 Oct 15 18:35 Aug.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 25 04:00 abc7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 26 07:00 def7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 27 10:00 ghi7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 28 13:00 jkl7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 29 16:00 mno7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 30 19:00 pqr7.txt

我只想列出 8 月创建的文件,而不是列出 10 月创建但名称为 8 月的第一个文件。下面应该是输出

-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 25 04:00 abc7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 26 07:00 def7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 27 10:00 ghi7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 28 13:00 jkl7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 29 16:00 mno7.txt
-rwxr-xr-x@   1 PrashastKumar  staff     0 Aug 30 19:00 pqr7.txt

另外,我想将月份作为用户输入而不是硬编码值。

答案1

您应该考虑替代方案解析ls,即充满多重陷阱。但是,由于您在这里的主要兴趣似乎是如何按列进行过滤,并且您的最终目标可能不是ls 无论如何解析,所以我将继续并坚持您正在使用的示例(使用ls)。不过,请不要认为这意味着解析ls输出是一件好事。这通常不是一件好事。

当您grepfor时Aug,您正在一行中的任何位置搜索它。实际上,您不想选择包含Aug任何位置的行,而只想选择那些将其作为第六列的完整且准确文本的行。虽然你这样做grep会更容易、更自然awk

ls -la | awk '$6 == "Aug"'

如果由于某种原因你真的想要执行此操作grep,您可以:

ls -la | grep -E '(\S+\s+){5}Aug\s'

你是也有兴趣过滤第六列等于已读入 shell 变量的值的行month。您已经观察到这确实不是工作:

ls -la | awk '$6 == "$month"'   # does not work

不起作用的原因是单引号AWK 脚本周围$6 == "$month"阻止 shell 执行参数扩展$month其替换为其值。文本$month按原样传递到awk,这不是您想要的。AWK 变量和 shell 变量是完全分开的。解决此问题的一种干净而简单的方法是使用命令awk-v选项从 shell 变量初始化 AWK 变量:

ls -la | awk -v m="$month" '$6 == m'

如果您愿意,您可以将 AWK 变量命名为与 shell 变量相同的名称。在这种它们代表相同事物的情况下,这是一个合理的选择。我将 AWK 变量命名为m,以说明 shell 和 AWK 变量如何分开并避免混淆。 (对于长或复杂的 AWK 脚本,或者具有许多变量的脚本,您可能希望以更具描述性的方式命名变量m,而不仅仅是 ,但在这种情况下,不会牺牲可读性。)


我在上面链接了主题Bash 参考手册因为你已经标记了你的问题除了最古老的 OS X 版本(现在称为 macOS)之外,所有版本的默认 shell 都是bash.在非常旧的版本中是tcsh.

作为旁注,您提到您使用month命令将 的值作为输入read month。当您使用 shell 的read命令时,您几乎应该总是传递该-r标志,从而改为 write read -r month。仅-r当您省略时read翻译\它收到的输入中的转义命令(您实际上永远不想要这种情况)。您可能还想使用IFS= read -r month,因此前导和尾随空格不会被删除。但在这种情况下,您可能确实希望将其删除,因此可以省略IFS=.

答案2

这对我有用

ls -al | awk '$6 == "Aug" {print}'

相关内容