通过stdin处理输入但文件输入工作正常时出现意外行为

时间:2018-09-28 14:06:19

标签: bash shell

我有一个转置矩阵的程序。将文件作为参数传递时,它可以正常工作,但是当通过stdin输入时,它会提供奇怪的输出。

这有效:

$ cat m1
1   2   3   4
5   6   7   8

$ ./matrix transpose m1
1   5   
2   6   
3   7   
4   8

这不是:

$ cat m1 | ./matrix transpose
5
[newline]
[newline]
[newline]

这是我用来转置矩阵的代码:

function transpose {
    # Set file to be argument 1 or stdin 
    FILE="${1:-/dev/stdin}"
    if [[ $# -gt 1 ]]; then
        print_stderr "Too many arguments. Exiting."
        exit 1
    elif ! [[ -r $FILE ]]; then
        print_stderr "File not found. Exiting."
        exit 1
    else
        col=1
        read -r line < $FILE
        for num in $line; do
            cut -f$col $FILE | tr '\n' '\t'
            ((col++))
            echo
        done
        exit 0
    fi
}

这段代码处理传递的参数:

# Main
COMMAND=$1
if func_exists $COMMAND; then
    $COMMAND "${@:2}"
else
    print_stderr "Command \"$COMMAND\" not found. Exiting."
    exit 1
fi

我知道this answer,但是我不知道哪里出了问题。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

for num in $line; do
    cut -f$col $FILE | tr '\n' '\t'
    ((col++))
    echo
done

此循环一次又一次地为每一列读取$FILE。这对于文件来说效果很好,但不适用于stdin,stdin是只能读取一次的数据流。

一种快速的解决方法是将文件读入内存,然后使用<<<将其传递给readcut

matrix=$(< "$FILE")
read -r line <<< "$matrix"
for num in $line; do
    cut -f$col <<< "$matrix" | tr '\n' '\t'
    ((col++))
    echo
done

有关An efficient way to transpose a file in Bash的各种更有效的一站式解决方案。