在 Linux 中读取用户输入

Pra*_*ast 2 shell macos

我编写了一个脚本,用于根据用户读取的月份列出文件,如下所示:-

echo "Enter Month"
read month
ls -al | awk '$6 == "$month" {print}'
Run Code Online (Sandbox Code Playgroud)

我在八月给用户输入,我没有得到任何结果。但是当我写作的时候

ls -al | awk '$6 == "Aug" {print}'
Run Code Online (Sandbox Code Playgroud)

我得到了确切的结果。难道我做错了什么?请帮忙

Kam*_*ski 8

主要的是:变量名不在单引号内扩展。这是一条“更好”(即错误少一点)的行:

ls -al              | awk '$6 == "'"$month"'" {print}'
# this is in single quotes ^^^^^^^          ^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

但:

  1. 尽管如此,这可能会在某些语言环境中失败。可能是事先设置LC_ALL=C好。
  2. 有了$month你可以注入(几乎?)任何东西进入awk。有更好的方法来使用变量awk-v选项应该更安全(感谢 user000001 指出这一点)。
  3. 您不应该首先解析 的输出ls

正确的解决方案可能使用findstat。以下代码可能不是最快的解决方案,但由于以下原因,它更健壮:

  • 丢弃$month与预定义值不匹配的值,
  • 使用find而不是解析ls.

编码:

#!/bin/sh
echo "Enter Month"
read month
case "$month" in
  1|01|Jan|jan|January|january)   monthN=01;;
  2|02|Feb|feb|February|february) monthN=02;;
# ...
  10|Oct|oct|October|october)     monthN=10;;
# ...
  *) echo Error! >&2; exit 1;;
esac
find ./ -maxdepth 1 -exec sh -c '[ `stat -c %y "$1" | cut -c 6-7` = "$2" ]' sh {} "$monthN" \; -ls
Run Code Online (Sandbox Code Playgroud)

我在 Debian 上对此进行了测试;它可能不是超级便携。不过,它显示了一般方法。

最后一行为当前目录中的每个对象(包括./它自己)调用一个单独的 shell 。这个 shell 用于stat获取 mtime 信息,然后从中cut提取两位数的月份数。[ ... ]将结果与所选月份数进行比较。如果此测试成功,则对对象find执行自己的测试ls(您可以使用-print-print0代替)。

请注意,这永远不会返回../。另一方面,find允许您使用其他测试(如-type f),因此这种方法非常灵活。

  • 在破坏列表中添加另一项:您使用字符串插值将变量传递给 awk,而不是使用更安全的 `-v` 选项。 (2认同)