shell : 如何在这个 Grep 结构中使用 UDV 而不会出现问题?

shell :How to use UDV in this Grep structure without having issues?

我有一个作业要求我在屏幕上打印比给定数字长的单词数,比方说 k ,它是从键盘上读取的。然后订购结果。 直到现在我决定以这种方式尝试:

#!bin/bash
k=0
if [ $# -eq 0 ]
then 
    echo "No argument supplied."
    exit 1
fi
echo -n "Give the minimal lenght of the words : "
read k 
for files in "$@"
do
    if [ -f "$files" ]; then
        echo "$(cat $files | egrep -o '[^ ]{k,}' $files | wc -w) : $files."
    else
        echo "Error: File $files has not been found."
    fi
done | sort -n

我的问题是,每当我在 "egrep -o '[^ ]{k,}'" 部分使用 k 尝试这个程序时,它总是给出错误的答案。但是如果我用一个整数替换它,in 就会完全按照我的意愿工作。 使此代码适用于从键盘读取的 k 的正确方法是什么?这是语法,不能真正理解我应该怎么写,尝试了其他方式来喜欢“$k”、$k、((k))、k。 欢迎任何帮助,请提示是否有人可以给我?我卡住了

尝试

echo "$(egrep -o '[^ ]{'"$k"',}' "$files" | wc -w): $files"
  • 您的直接问题是使用 k 而不是 $k
    • 要引用 Bash 中的变量,您必须在其名称前加上 $ 前缀(相比之下,当 赋值 到它)。在某些情况下,为了将变量名称与后续标记分开,您必须将名称括在 {..} 中,例如 ${k},您也可以选择这样做以提高视觉清晰度,即使它不是严格要求的.
  • 您的下一个问题是使用 引号来分隔 egrep 搜索正则表达式(在命令替换内),这会阻止变量引用的扩展。
    • 请注意,即使您使用的是双引号字符串 总体而言,嵌入式命令替换 ($(...)) 也是它们自己的世界,其中通常的解析规则apply(单引号字符串是文字,而双引号字符串可能包含嵌入的变量引用、命令替换、算术扩展)。
  • 但是,简单地使用 double 引号代替 - 在其中变量引用 扩展 - 会 可能 修复问题在这种情况下由于bash 3.2.57 与命令替换中的 brace expansion ({...}) 有关:
    • 此错误在 bash 4.3.30 中不再存在(不知道何时修复),因此您可以 使用单、双- 引号字符串:"[^ ]{$k,}"。但是,所提供的解决方案适用于 bash 3.x 和 4.x
    • 这是一个演示 bash 3.2.57 中错误的最小示例:
      • k=3; echo "$(egrep -co "[^ ]{$k,}" <<<$'abc\nde')"
      • 这个应该return1,但是returns 0 2,由于错误地将大括号扩展应用到{3,}(产生 两个 字符串:egrep -co '[^ ]3'egrep -co '[^ ]'),即使它包含在双引号字符串中。
  • 因此,答案是拼接两个引号字符串[=91]之间的变量引用=]:
    • '[^ ]{'"$k"',}' 将文字 [^ ]{ 与变量 $k 和文字 ,} 的值连接起来。例如,如果 $k4,则 egrep 会看到以下字符串:[^ ]{4,}
  • (此外,初始的 cat $files | 是不必要的,因为该文件也作为 操作数 (非选项参数)传递,并且您应该始终双引用包含文件名的变量,因此该命令不会中断带有嵌入空格的文件名。)
  • 最后,我建议将 $files 重命名为 $file 以避免混淆:在循环的每次迭代中,您只处理 单个 文件。