2017-10-05 344 views
3

我想制作一个接受元音的shell脚本,并在文本文件“abc.txt”中输出该元音的出现次数。grep语句不适用于case语句

下面的脚本作品完美(脚本打印元音“A”的文本文件中“的abc.txt”出现的次数):

#!/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 

我迷路了,为什么当我把他们casegrep报表不显示任何内容声明。

回答

3

多个问题,但主要导致您的问题的一个问题是没有使用case构造中的变量。使用ch只是一个常量,并且与以下任何表达式都不匹配。

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

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

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

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

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

如果你想改善命令,你可以尝试''grep -oci“$ vovel”''(不区分大小写的grep),当vovel不需要验证时。 – allo

+0

grep -oc [aA] abc.txt和grep -oci'a'abc.txt似乎不起作用。不管有多少个a,都返回1。 – Jaspreet

+0

@Jaspreet:它对我来说工作得很好。你能告诉我们'abc.txt'什么命令字符,您在搜索为 – Inian

1

你的问题是不是这样的说法,但是,你正在使用的变量分配以错误的方式

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

你正在运行-o [aA] abc.txt分配grep变量x,如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可能不完全兼容,所以使用特定的外壳是一个好主意,反正。

+0

'$(...)'不是特定于'bash';这是任何POSIX兼容shell中命令替换的首选语法。 – chepner

+0

谢谢,我将它添加到答案中,并链接了一个相关答案。 – allo

1

您的选项都不是“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语句可言,或单独回声输出的计数。 如果您确实需要使用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使用来算occurrances,而不是匹配的行。我几乎建议-cgrep消除额外的命令,直到我再次看。尼斯。 :)