我在使用Ubuntu 17.04机器编写的bash脚本时遇到了一个非常奇怪的问题。
我有一个txt文件,其中包含有关此方式的人员信息:
号码姓氏城市州
通过这些信息,我必须创建一个按州运作的组织系统。例如,使用像这样的列表
123阿兰史密斯new_york NEW_YORK
123 bob smith buffalo NEW_YORK
123 charles smith los_angeles CALIFORNIA
123 dean smith mobile ALABAMA
计算结束时的结果应该是三个名为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
我在这里做错了什么?而且,为什么它不告诉我某些事情是错的(显然有)?
答案 0 :(得分:0)
直接的问题(由@that其他人指出)是在行:
test -e `head -n$i | tail -n1 | cut -f5 --delimiter=" "`
head
命令没有给出要读取的文件名,所以它从stdin(即你)读取。但是我会彻底改变整个剧本,因为你是以非常低效的方式进行的。如果你有一个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运行脚本,因为它会指出其他一些问题(例如,未引用的变量引用)。