【问题标题】:grep statement is not working inside case statementgrep 语句在 case 语句中不起作用
【发布时间】:2017-10-05 08:57:39
【问题描述】:

我想制作一个接受元音并在文本文件“abc.txt”中打印该元音出现次数的 shell 脚本。

以下脚本完美运行(用于打印文本文件“abc.txt”中元音“a”出现次数的脚本):

#!/bin/bash
grep -o [aA] abc.txt|wc -l

但我想为所有元音实现这个,所以我这样做了:

#!/bin/bash
echo -n "Enter the desired vowel: "
read ch
case ch in
a) grep -o [aA] abc.txt|wc -l;;
A) grep -o [aA] abc.txt|wc -l;;
e) grep -o [eE] abc.txt|wc -l;;
.
.
.
U) grep -o [uU] abc.txt|wc -l;;
esac

代码执行,但在我输入所需的元音后,没有显示任何内容。我也试过这个(但结果和上面的代码一样):

#!/bin/bash
x=0
echo -n "Enter the desired vowel: "
read ch
case ch in
a) x=grep -o [aA] abc.txt|wc -l;echo $x;;
A) x=grep -o [aA] abc.txt|wc -l;echo $x;;
e) x=grep -o [eE] abc.txt|wc -l;echo $x;;
.
.
.
U) x=grep -o [uU] abc.txt|wc -l;echo $x;;
esac

我不知道为什么当我将 grep 语句放在 case 语句中时它们没有显示任何内容。

【问题讨论】:

    标签: linux bash shell sh


    【解决方案1】:

    多个问题,但导致您问题的主要原因是未在 case 构造中使用变量。使用ch 只是一个常量,不匹配以下任何表达式。

    case "$ch" in
    #    ^^^^^ This needs to be a variable used in read command
    

    此外,要存储命令的输出,您需要使用$(cmd) 类型的命令替换语法。此外,您可以使用 -c 标志而不是 grep .. | wc -l 来返回匹配字符串的总数。

    x=$(grep -oc '[aA]' abc.txt); echo "$x"
    

    (或)甚至改进的grep 命令是启用与-i 标志的不区分大小写匹配

    x=$(grep -oci 'a' abc.txt); echo "$x"
    

    【讨论】:

    • 如果你想改进命令你可以试试grep -oci "$vovel"(不区分大小写的grep),当元音不需要验证时。
    • grep -oc [aA] abc.txt 和 grep -oci 'a' abc.txt 似乎不起作用。无论存在多少 a,两者都只返回 1。
    • @Jaspreet:对我来说工作正常。你能告诉我们abc.txt你在搜索什么命令字符
    • The code: #!/bin/bash echo -n "Enter the desired vowel: " read ch case ch in a) grep -oci 'a' abc.txt;; A) grep -oci 'a' abc.txt;; e) grep -oci 'e' abc.txt;; . . . U) grep -oci 'u' abc.txt;; esac The content in abc.txt: aaAA eeEe iIII oOOo UUUu
    • @Jaspreet:你还没有修复case "$ch" in。在声称不工作之前,请按照答案中的代码修复代码!
    【解决方案2】:

    您的问题不是 case 语句,而是您以错误的方式使用变量赋值

    x=grep -o [aA] abc.txt|wc -l;echo $x
    

    您将grep 分配给变量x 以运行-o [aA] abc.txt,因为var=something command 分配变量只是为了运行command

    这当然没有意义,但你可以庆幸你没有尝试像x=something rm * 这样会删除你的文件的东西。

    正确的语法是

    x="`grep -o '[aA]' abc.txt|wc -l`"
    

    这意味着在子shell中执行grep|wc并将结果分配给变量x。我添加了引号,因为当您的命令不返回任何内容时,您会遇到不带引号的问题,因为 x= 是语法错误,而 x="" 完全没问题。

    在 bash 中你有很好的语法(可以嵌套)

    x="$(grep -o '[aA]' abc.txt|wc -l)"
    

    也是如此。但请务必以#!/bin/bash 开始您的脚本,因为/bin/sh 通常是另一个shell,而不是bash,其中语法可能不起作用。

    $() 应该适用于每个fully POSIX compatible shell,但/bin/sh 可能不完全兼容,因此无论如何使用特定的 shell 是个好主意。

    【讨论】:

    • $(...) 不特定于bash;它是任何 POSIX 兼容 shell 中命令替换的首选语法。
    • 谢谢,我已将其添加到答案中并链接了相关答案。
    【解决方案3】:

    您的选项都不是“ch”,因此没有执行任何行。 如果您使用“$ch”然后输入与您的案例之一匹配的内容,它会将“grep”分配给 x,然后尝试执行 -o 并可能引发错误。

    其他人已经解释过你应该使用像x="$(grep ...)" 这样的结构,以及在你的字符集周围需要引号,所以我不会再为这些而责备你了。 :)

    如果您打算使用 grep,您可以尝试使用 -i 而不是字符类来进行不区分大小写的匹配。

    如果可能,请尝试重构您实际问题的逻辑,以尽可能简化代码。这样做可能会更好:

    echo -n "Enter the desired vowel: "
    read ch
    grep -io "$ch" abc.txt | wc -l
    

    这根本不需要 case 语句,也不需要单独的 echo 来输出计数。 如果您确实决定需要 case 语句,有时也有助于简化代码以减少冗余。

    #!/bin/bash
    typeset -l ch # forces value to lowercase to make case easier
    file=abc.txt  # used more than once, so put in a var to ease maintenance
    echo -n "Enter the desired vowel: "
    read ch       # will be lowercase no matter what they enter
    case "$ch" in # so we only have to match lower cases
    [aeiou]) grep -io "$ch" | wc -l ;; # reads stdin, writes to stdout
    *) echo "That's not a valid vowel" >&2 # write to STDERR to keep separate
       exit 1 ;;                           # handle invalid inputs
    esac < $file > match.count # all case I/O managed in one place here
    echo "There are $(<match.count) $ch's in $file"
    

    顺便说一句,我真的很喜欢您使用 -owc -l 来计算出现次数而不是匹配行数。我几乎在grep 中建议-c 消除额外的命令,直到我再次查看。好的。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 2018-09-19
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      相关资源
      最近更新 更多