2017-10-20 13 views
0

私は、Ubuntu 17.04マシンで書かれたbashスクリプトに非常に奇妙な問題があります。Bash - if文が自動的に動作しない

数名の姓の都市国家

私は状態によって働く組織のシステムを作成する必要があり、これらに関する情報付:

私はこのやり方ではユーザーに関する情報が含まれているtxtファイルを持っています。例えば、この

123アラン・スミスNew_YorkのNEW_YORK

123ボブ・スミスバッファローNEW_YORK等リストスミスカリフォルニア

123ディーン・スミス携帯ALABAMA

結果los_angeles

123チャールズと計算の最後には、そこに住む人々を含むNEW_YORK、CALIFORNIA、ALABAMAの3つの新しいファイルが必要です。

スクリプトは、名前のリストをパラメータとして受け取ります。私はifステートメントを実装しました(ある状態に住んでいる人が多い場合に備えて、ファイルの存在のテストによって指定された条件は、forループの中にあります。が走っています。結果は正しいです、私はそれらの上に適切な人々とファイルを取得しますが、それはコードを動作させるために私は入力を押す必要が私をうなずける、それは私には意味がありません。

は、ここに私のコードです:

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

は、私がここで間違って何をしているのですか?そして、なぜ、何かが間違っていることがわかりません(明確に存在します)?あなたはすなわち(

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

headコマンドが読み出さするファイル名を与えられていないので、それは標準入力から読んでいる:

+3

'test -e'行はファイルから読み込みません。それはあなたから読まれます。たぶん、 '-n $ i" $ 1 "'を代わりにしたかったでしょうか? (テストは不要ですが、最初に '>'を使う必要はありません。 '' 'はファイルが存在しないときにも作成します) –

+0

これは動作していますか?どのように呼びますか? stdinを読み込んでいるようですが、...ファイルを状態別に解析するだけですか? –

答えて

0

当面の問題は、(@that他の人によって指摘)の行にということです)。しかし、私は非常に非効率な方法でそれをやっているので、スクリプト全体を大幅に変更したいと思います。例えば、1000行のファイルがある場合は、最初の行(実際には3回)、次に最初の2行(3回)、次に最初の3行を読むにはheadを実行します。完了すると、headはファイルの最初の行を3000回読み取った後、tailはそれらの2997を破棄しました。あなたは本当にそれを一度読む必要がありました。

このようなファイルを反復処理するとき、あなたはこのようなもので、ファイルのライン・バイ・ラインを読んでオフはるかに良いです:

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

しかし、この場合には、より良いツールがあります。 awkは、このようなファイルを処理で本当に良いです、それは本当に簡単にタスクを処理することができます:

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

(注:私はまた、5番目のフィールド/空白行を無視するがあることを確認するifに入れることがなければ。それがちょうどawk '{ print $0 >>$5 }' "$1"だったことを確認してください)。

はまた、コマンド:

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

...これを行うには、本当に奇妙な、壊れやすい方法です。 lsの出力を解析することは一般的に悪い考えです、そして再びそれを行うにははるかに簡単な方法があります:それはいくつかの他の問題(例えば指摘ますので、

rm *[A-Z] 

は最後に、私は、shellcheck.netを通して、あなたのスクリプトを実行することはお勧め引用されていない変数参照)。