2012-03-15 119 views
1

我在这里有这个shell脚本,它正在做我想做的事情。但是,当我试图在最后打印出变量时,附加到小,中或大的$ file变量不显示在标准输出中。壳在这里做什么,我能做些什么来解决它?这里发生了什么? Shell编程

#!/bin/sh 

# sorts txt files into small, medium and large 
# depending on number of lines 
# small <= 10 
# medium <= 100 
# large > 100 

small="Small Files:" 
medium="Medium Files:" 
large="Large Files:" 

for txtFile in *.txt 
do 
    wc -l $txtFile 
done | 
while read lineCount file 
do 
    if [ $lineCount -lt 10 ] 
    then 
     small="$small $file" 

    elif [ $lineCount -lt 100 ] 
    then 
     medium="$medium $file" 
    else 
     large="$large $file" 
    fi 
done 
echo "$small" 
echo "$medium" 
echo "$large" 

回答

3

当您使用管道时,管道的各个阶段作为单独的进程运行,并且分配的变量不会传播回主进程。你可以不喜欢这样,而不是:

small="Small Files:" 
medium="Medium Files:" 
large="Large Files:" 

for txtFile in *.txt 
do 
    wc -l $txtFile 
done | (
    while read lineCount file 
    do 
    if [ $lineCount -lt 10 ] 
    then 
     small="$small $file" 
    elif [ $lineCount -lt 100 ] 
    then 
     medium="$medium $file" 
    else 
     large="$large $file" 
    fi 
    done 
    echo "$small" 
    echo "$medium" 
    echo "$large" 
) 

括号导致while循环和回声语句组合成一个单一的过程,所以变量值被保留。

你可以在一个简单的例子看到这种效果:

x=5;echo | x=6;echo $x 

将打印5,而

x=5;echo | (x=6;echo $x) 

将打印6.

1

您还可以使用进程替换,虽然可读性受到一些影响:

while read lineCount file; do 
    if [ $lineCount -lt 10 ]; then 
    small="$small $file" 
    elif [ $lineCount -lt 100 ]; then 
    medium="$medium $file" 
    else 
    large="$large $file" 
    fi 
done < <(wc -l *txt) 

这是可行的,因为它删除了管道,所以while循环在当前shell中运行。

+0

好的解决方案,但请注意,这只是反转角色:'wc'仍然在子shell中运行。 – l0b0 2012-05-14 14:50:33

+0

这里只有其他问题是OP使用'#!/ bin/sh',并且在基准POSIX sh中进程替换不可用。 – 2014-09-18 21:08:42

相关问题