我在编写bash脚本时遇到了问题。我需要编写一个可以通过两种方式调用的脚本,读取文件或读取标准输入。然而,当我使用while-read时,我无法再让它读取标准输入。这是我的代码:
#!/bin/bash
FILE=$1
while read LINE;
do
echo "$LINE" | tr " " "\n" | tr "\t" "\n"
done < $FILE
我在编写bash脚本时遇到了问题。我需要编写一个可以通过两种方式调用的脚本,读取文件或读取标准输入。然而,当我使用while-read时,我无法再让它读取标准输入。这是我的代码:
#!/bin/bash
FILE=$1
while read LINE;
do
echo "$LINE" | tr " " "\n" | tr "\t" "\n"
done < $FILE
#!/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。
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
-
通常被视为标准输入。但是,应避免使用 /dev/stdin
,因为有很多情况它无法按预期工作。而且通过强制使用 -
命令脚本就无法从管道读取数据。 - vdavidfile=$(</dev/stdin)
的行为更好。 - George Vasilioucmd | tool -
。除此之外,我为什么要避免使用/dev/stdin
?请在这些“许多”情况下详细介绍一下。 - hek2mglbash
保证当用于重定向时,/dev/stdin
指的是标准输入,无论文件系统实际上是否有这样的入口。 file = $(< /dev/stdin)
将一次性读取整个文件,这可能不是您想要做的事情。 - chepner
lsof -a -p $$ -d0
。 - vdavid