2

我有一个任务要求我在屏幕上打印比给定数字长的单词数,比如说 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 尝试这个程序时,它总是给出错误的答案。但是如果我用一个整数替换它,就可以完全按照我的意愿工作。使此代码适用于从键盘读取的 k 的正确方法是什么?这是语法,无法真正理解我应该如何写在那里,尝试了其他方式来喜欢 "$k" , $k , ((k)) ,k。欢迎任何帮助,如果有人可以给我一个提示吗?我被困住了

4

1 回答 1

1

尝试

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