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

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

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

Bash中也有类似的功能吗?


当前回答

Use:

for line in `cat`; do
    something($line);
done

其他回答

Perl的行为,OP中给出的代码可以不带参数,也可以有多个参数,如果一个参数是一个连字符-这被理解为stdin。此外,文件名总是可能带有$ARGV。 到目前为止给出的答案都没有真正模仿Perl在这些方面的行为。这里有一个纯Bash的可能性。诀窍在于适当地使用exec。

#!/bin/bash

(($#)) || set -- -
while (($#)); do
   { [[ $1 = - ]] || exec < "$1"; } &&
   while read -r; do
      printf '%s\n' "$REPLY"
   done
   shift
done

文件名可在$1。

如果没有给出参数,则人为地将-设置为第一个位置参数。然后循环参数。如果参数不是-,则使用exec重定向filename中的标准输入。如果重定向成功,则使用while循环进行循环。我使用标准的REPLY变量,在这种情况下,您不需要重置IFS。如果你想要另一个名字,你必须像这样重置IFS(当然,除非你不想这样做,并且知道你在做什么):

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

这个很容易在终端上使用:

$ echo '1\n2\n3\n' | while read -r; do echo $REPLY; done
1
2
3

Use:

for line in `cat`; do
    something($line);
done

也许最简单的解决方案是使用合并重定向操作符重定向标准输入:

#!/bin/bash
less <&0

标准输入是文件描述符0。上面的代码将通过管道传输到bash脚本的输入发送到less的标准输入中。

阅读有关文件描述符重定向的更多信息。

代码${1:-/dev/stdin}只理解第一个参数,所以你可以这样使用:

ARGS='$*'
if [ -z "$*" ]; then
  ARGS='-'
fi
eval "cat -- $ARGS" | while read line
do
   echo "$line"
done