读取文件或读取标准用户输入

3

我在编写bash脚本时遇到了问题。我需要编写一个可以通过两种方式调用的脚本,读取文件或读取标准输入。然而,当我使用while-read时,我无法再让它读取标准输入。这是我的代码:

#!/bin/bash
FILE=$1
while read LINE; 
do
    echo "$LINE" | tr " " "\n" | tr "\t" "\n"
done < $FILE
2个回答

3
问题出在你总是将 $FILE 作为输入传给 read 命令。 如果有参数,可以尝试将文件重定向到通道0,并且不带参数则使用stdin。
#!/bin/bash
FILE=$1
if [ ! -z "$FILE" ]
then
  exec 0< "$FILE"
fi
while read LINE
do
    echo "$LINE" | tr " " "\n" | tr "\t" "\n"
done

"

exec 0< "$FILE"告诉shell将$FILE作为通道0的输入。提醒:默认情况下,read监听通道0。

这里的关键是0<,其中0表示通道0,<表示这是一个输入。当没有参数时,exec 0< "$FILE"不会被调用,在这种情况下,通道0将使用stdin。

"

顺便说一下,我倾向于说“通道0”,但对于Bash来说确切的术语是“文件描述符0”。您可以使用以下命令检查当前fd0:lsof -a -p $$ -d0 - vdavid
谢谢伙计,我刚刚对这门语言进行了进一步的研究,目前还是个新手 :P。 - C.Smith

2

UNIX 工具通常使用特殊的文件名-来表示输入来自标准输入(stdin)。您可以进行适应:

file="${1}"
if [ "${file}" = "-" ] ; then
    file=/dev/stdin # special device for stdin
fi

while read -r line ; do
    do something
done < "${file}"

您现在可以像这样调用该工具

tool -             # reads from terminal
cmd | tool -       # used in a pipe
tool /path/to/file # reads from file

谢谢你的回答,我会尝试并进一步学习bash。我还是这门语言的初学者 :) - C.Smith
同意 - 通常被视为标准输入。但是,应避免使用 /dev/stdin,因为有很多情况它无法按预期工作。而且通过强制使用 - 命令脚本就无法从管道读取数据。 - vdavid
在某些情况下,赋值file=$(</dev/stdin)的行为更好。 - George Vasiliou
@vdavid 当然可以在管道中使用它: cmd | tool -。除此之外,我为什么要避免使用/dev/stdin?请在这些“许多”情况下详细介绍一下。 - hek2mgl
bash 保证当用于重定向时,/dev/stdin 指的是标准输入,无论文件系统实际上是否有这样的入口。 file = $(< /dev/stdin) 将一次性读取整个文件,这可能不是您想要做的事情。 - chepner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接