2012-11-11 16 views
0

我試圖創建一個shell腳本,它將給定的數字相加。如果沒有給定的參數,那麼它會嘗試讀取管道輸出,但是我得到一個錯誤。參數輸入工作,但管道不是

#!/bin/sh 

sum=0 

if [ $# -eq 0 ] 
then 
    while read data 
    do 
    sum=`expr $sum + $data` 
    done 
else 
    for (( i = 1 ; i <= $#; i++ )) 
    do 
    sum=`expr $sum + ${!i}` 
    done 
fi 

echo $sum 

這工作:sum 10 12 13 但是這一次沒有:echo 10 12 13| sum

由於提前,

+0

你正在使用'bash',對吧?因爲你的for循環不是'sh'循環。 –

+0

對不起,我是初學者。我真的不明白 –

+0

好吧,讓我們假設你正在使用'bash'。它不起作用,因爲在第二種情況下,變量'data'包含'10 12 13' ... –

回答

3

在這裏你去(假設bash,不sh):

#!/bin/bash 

sum=0 

if (($# == 0)); then 
    # Read line by line 
    # But each line might consist of separate numbers to be added 
    # So read each line as an array! 
    while read -a data; do 
    # Now data is an array... but if empty, continue 
    ((${#data[@]})) || continue 
    # Convert this array into a string s, with elements separated by a + 
    printf -v s "%s+" ${data[@]} 
    # Append 0 to s (observe that s ended with a +) 
    s="${s}0" 
    # Add these numbers to sum 
    ((sum += s)) 
    done 
else 
    # If elements come from argument line, do the same! 
    printf -v s "%s+" [email protected] 
    # Append 0 to s (observe that s ended with a +) 
    s="${s}0" 
    # Add these numbers to obtain sum 
    ((sum = s)) 
fi 

echo $sum 

你可以這樣調用它:

$ echo 10 12 13 | ./sum 
35 
$ ./sum 10 12 13 
35 
$ # With several lines and possibly empty lines: 
$ { echo 10 12 13; echo; echo 42 22; } | ./sum 
99 

希望這會有所幫助!

編輯。您可能也有興趣學習關於IFS的酷東西。我注意到人們往往會在bash中混淆@*。如果你不知道我在說什麼,那麼你應該使用@而不是*,也可以用於數組下標!在bash手冊中,您會發現當雙引號時,$*(或${array[*]})展開爲由IFS的值分隔的數組的所有元素。這在我們的情況下可能很有用:

#!/bin/bash 

sum=0 

if (($# == 0)); then 
    # Read line by line 
    # But each line might consist of separate numbers to be added 
    # So read each line as an array! 
    while read -a data; do 
    # Now data is an array... but if empty, continue 
    ((${#data[@]})) || continue 
    # Setting IFS=+ (just for the sum) will yield exactly what I want! 
    IFS=+ sum=$((sum + ${data[*]})) 
    done 
else 
    # If elements come from argument line, do the same! 
    # Setting IFS=+ (just for the sum) will yield exactly what I want! 
    IFS=+ sum=$(($*)) 
fi 

echo $sum 

Gniourf現在退出教師模式。 :-)

+0

對不起,先生,但我必須在開始時使用'#!/ bin/sh'。謝謝你幫助我,但是我怎樣才能在sh中讀取-a數據?如果我在讀數據的同時將'while read data'替換爲'',那麼我不會收到任何錯誤消息,但結果是第一個數字(10) –

+1

@DonPavilon您需要使用'$ {data [@]} '獲取一個數組(嘗試'echo「$ {data [@]}」'來打印數組)。如果你使用'bash'命令,爲什麼你需要使用'#!/ bin/sh'? –

+0

現在我明白這一切。謝謝你的幫助先生! –