下面的Perl脚本(my.pl)既可以从命令行参数中的文件读取,也可以从标准输入(STDIN)读取:

while (<>) {
   print($_);
}

Perl my.pl将从标准输入中读取,而Perl my.pl .txt将从a.txt中读取。这很方便。

Bash中也有类似的功能吗?


当前回答

下面的解决方案从文件读取(如果脚本调用时将文件名作为第一个参数$1),否则从标准输入读取。

while read line
do
  echo "$line"
done < "${1:-/dev/stdin}"

替换${1:-…}如果定义了,则接受$1。否则,使用自己进程的标准输入的文件名。

其他回答

每当IFS中断输入流时,回显解决方案就添加新行。@fgm的回答可以稍微修改一下:

cat "${1:-/dev/stdin}" > "${2:-/dev/stdout}"

我觉得这些答案都不能接受。特别是,接受的答案只处理第一个命令行参数,而忽略其余的。它试图模拟的Perl程序处理所有命令行参数。所以公认的答案甚至不能回答问题。

其他答案使用Bash扩展,添加不必要的“cat”命令,只适用于简单的输入输出回显情况,或者只是不必要的复杂。

然而,我必须给他们一些赞扬,因为他们给了我一些想法。以下是完整的答案:

#!/bin/sh

if [ $# = 0 ]
then
        DEFAULT_INPUT_FILE=/dev/stdin
else
        DEFAULT_INPUT_FILE=
fi

# Iterates over all parameters or /dev/stdin
for FILE in "$@" $DEFAULT_INPUT_FILE
do
        while IFS= read -r LINE
        do
                # Do whatever you want with LINE here.
                echo $LINE
        done < "$FILE"
done

更准确的说……

while IFS= read -r line ; do
    printf "%s\n" "$line"
done < file

与…

while read line
do
    echo "$line"
done < "${1:-/dev/stdin}"

我得到以下输出:

忽略标准输入中的1265个字符。使用“-stdin”或“-”来说明如何处理管道输入。

然后决定用for:

Lnl=$(cat file.txt | wc -l)
echo "Last line: $Lnl"
nl=1

for num in `seq $nl +1 $Lnl`;
do
    echo "Number line: $nl"
    line=$(cat file.txt | head -n $nl | tail -n 1)
    echo "Read line: $line"
    nl=$[$nl+1]
done

这是最简单的方法:

#!/bin/sh
cat -

用法:

$ echo test | sh my_script.sh
test

要将stdin分配给变量,您可以使用:stdin =$(cat -)或只是简单的stdin =$(cat)作为操作符是不必要的(根据@mklement0注释)。


要解析标准输入中的每一行,请尝试以下脚本:

#!/bin/bash
while IFS= read -r line; do
  printf '%s\n' "$line"
done

要从文件或stdin中读取(如果参数不存在),您可以将其扩展为:

#!/bin/bash
file=${1--} # POSIX-compliant; ${1:--} can be used either.
while IFS= read -r line; do
  printf '%s\n' "$line" # Or: env POSIXLY_CORRECT=1 echo "$line"
done < <(cat -- "$file")

Notes: - read -r - Do not treat a backslash character in any special way. Consider each backslash to be part of the input line. - Without setting IFS, by default the sequences of Space and Tab at the beginning and end of the lines are ignored (trimmed). - Use printf instead of echo to avoid printing empty lines when the line consists of a single -e, -n or -E. However there is a workaround by using env POSIXLY_CORRECT=1 echo "$line" which executes your external GNU echo which supports it. See: How do I echo "-e"?

参见:当没有参数传递时如何读取stdin ?在stackoverflow SE