2013-05-30 74 views
1

我写了一个bash脚本,假设创建一些文件并写入它们。 无论如何它并不重要的脚本是什么,事情是 - 在代码中有一个评论(最后),它只是打印一些东西来屏幕。如果我试图像这样运行它 - 程序不会将输出写入文件,但是如果不将这行写入注释(即移除'##'),那么它就起作用 - 程序会将输出写入文件。 我真的尝试过,但我不明白发生了什么事... 如果你需要脚本的其余部分,或者更多的解释,它只是说什么。bash脚本的奇怪行为

files=(`ls $artists`) 
echo artists=%${files[*]}% 
for file in ${files[*]}; do 
    echo file= $file: 
    lines=`wc -l $artists/$file | cut -d" " -f1` 
    echo lines=$lines 
    counter=0 
    while read -a line; do 
     if (($counter==$lines));then 
      break; 
     fi 

     if [[ ! $line =~ [^[:space:]] ]] ; then 
      continue 
     fi 
     rank=$((${line[3]}+$((5*${line[4]})))) 
     echo ${line[*]} 
     echo rank = $rank 
     echo "${line[*]} $rank" >> $artists/$file 
     let counter++ 
    done < $artists/$file 

    ##cat $artists/$file | tail -$lines 
    cat $artists/$file | tail -$lines > $artists/$file 
done 
+2

[为什么你不应该解析ls(1)的输出](http://mywiki.wooledge.org/ParsingLs) –

+1

描述脚本的目标是什么会很有帮助。 – chepner

回答

2

重定向到源文件会损坏它。改为重定向到临时文件,然后重命名它。

+0

[这是为什么](http://mywiki.wooledge.org/BashPitfalls#cat_file_.7C_sed_s.2BAC8-foo.2BAC8-bar.2BAC8_.3E_file) – kojiro

+0

何所以这个问题....无论如何,这是HW和我不允许使用tmp文件...任何建议? thnks。 – rooster

0

cat $artists/$file | tail -$lines > $artists/$file

让我们看看是什么在做什么。首先,您正在运行cat程序,这是不必要的。它可能会影响症状,但我怀疑它。

壳已发现> $artists/$file。它将在运行tail程序之前将文件截断为零字节。根据事件的确切顺序,cat将读取一个空文件。

所以,不这样做,试试这个来代替:

if tail -$lines "$artists/$file" > "$artists/$file.$$" 
then 
    mv "$artists/$file.$$" "$artists/$file" 
else 
    echo "Unable to tail $artists/$file" >&2 
fi 

无需cat。我们重定向到一个临时文件名,其中附有PID($$)。如果tail工作,那么我们将临时文件重命名为所需的文件名,否则我们会向stderr(fd 2)写入错误消息。如果失败,您可能还会考虑是否想要跳出循环或退出程序。

防御性编制还要求我们在双引号内放置任何文件名变量,以防某些numpty在文件或目录名称(程序文件)中放入空格。

+0

thnks但正如我所说,不允许使用tmp文件 – rooster

+0

@rooster:为什么地狱不是? – cdarke

0

重定向到源文件将在下一个命令读取它之前截断文件。既然你提到过,你不能创建临时文件,如何创建命名管道

您可以像管道文件一样重新定向和读取管道。另外,你可以并行地做到这一点。

+0

好,那么在这种情况下我该如何做? – rooster