2017-10-20 119 views
0

我在Ubuntu 17.04機器上編寫的bash腳本有一個非常奇怪的問題。Bash - if語句不自動運行

我有一個包含約人以這種方式信息的txt文件:

數名姓城市國家

有了這些相關信息我要創建一個組織系統,通過國家的作品。例如,像這樣

123阿蘭·史密斯new_york NEW_YORK

123鮑勃·史密斯水牛NEW_YORK

123查爾斯列表史密斯los_angeles CALIFORNIA

123迪恩·史密斯阿拉巴馬州墨比爾

結果在計算結束時應該有三個名爲NEW_YORK,CALIFORNIA和ALABAMA的新文件包含住在那裏的人。

該腳本將名稱列表作爲參數。我在for循環中實現了一個if語句(該條件由文件的存在性測試決定,以防萬一有更多的人處於特定狀態),奇怪的是,除非我在程序中按Enter鍵才能運行在跑。結果是正確的,我得到了正確的人在他們的文件,但它讓我感到困惑,我不得不按下輸入來使代碼工作,這對我來說沒有意義。

這裏是我的代碼:

#!/bin/bash 

clear 

#finding how many file lines and adding 1 to use the value as a counter later 
fileLines=`wc -l addresses | cut -f1 --delimiter=" "` 
((fileLines = fileLines+1)) 

for ((i=1; i<$fileLines; i++)) 
do  
    #if the file named as the last column already exists do not create new one 
    test -e `head -n$i | tail -n1 | cut -f5 --delimiter=" "` 
    if [ $? = 0 ] 
    then 
     head -n$i $1 | tail -n1 >> `head -n$i $1 | tail -n1 | cut -f5 --delimiter=" "` 
    else 
     head -n$i $1 | tail -n1 > `head -n$i $1 | tail -n1 | cut -f5 --delimiter=" "` 
    fi 
done 

echo "cancel created files? y/n" 
read key 

if [ $key = y ] 
then 
    rm `ls | grep [A-Z]$` 
    echo "done" 
    read 
else 
    echo "done" 
    read 
fi 

clear 

什麼我錯在這裏做什麼?而且,爲什麼它沒有告訴我有什麼不對(顯然存在)?

+3

您的'test -e'行不會從文件讀取。它從您那裏讀取。也許你想要「頭 - 我$」$ 1「'而不是? (儘管測試是不必要的:第一次不需要使用'>',當不存在時也會創建文件) –

+0

這是行得通的嗎?你怎麼稱呼它?它看起來像是讀取標準輸入,但是......你只是想按照狀態解析文件的行嗎? –

回答

0

眼前的問題(由@that其他人指出)是在該行:

test -e `head -n$i | tail -n1 | cut -f5 --delimiter=" "` 

head命令沒有給出一個文件名從閱讀,因此它從標準輸入讀取(即你)。但是我會劇烈地改變整個腳本,因爲你以非常低效的方式來做它。如果你有一個1000行的文件,你可以運行head來讀取第一行(實際上是3次),然後是前兩行(三次),然後是前三行。完成後,head已經讀取了3000次文件的第一行,然後tail已經丟棄了那些次數的2997次。你只需要真正閱讀一次。

當通過這樣的文件迭代,你好得多僅僅閱讀文件中的行由行,像這樣的東西:

while read line; do 
    # process $line here 
done <"$1" 

但是在這種情況下,有一個更好的工具。 awk是在處理文件這樣真的很好,它真的可以簡單地處理任務:

awk '{ if($5!="") { print $0 >>$5 }}' "$1" 

(注:我也投入了if以確保有第五場/忽略空行如果沒有。檢查它會只是awk '{ print $0 >>$5 }' "$1")。

此外,命令:

rm `ls | grep [A-Z]$` 

...就是做這一個非常奇怪的和脆弱的方式。解析ls輸出通常是一個壞主意,再有一個更簡單的方法來做到這一點:

rm *[A-Z] 

最後,我建議通過shellcheck.net運行腳本,因爲它會指出一些其他問題(如未加引號的變量引用)。