2017-10-20 118 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运行脚本,因为它会指出一些其他问题(如未加引号的变量引用)。