2017-10-05 346 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消除額外的命令,直到我再次看。尼斯。 :)