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

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

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

Bash中也有类似的功能吗?


当前回答

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

#!/bin/bash
less <&0

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

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

其他回答

Use:

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

请尝试以下代码:

while IFS= read -r line; do
    echo "$line"
done < file

两种主要方法:

要么将参数文件和stdin管道到单个流和处理,就像stdin(流方法) 或者重定向stdin(和参数文件)到一个命名管道和进程,就像一个文件(文件方法)

流的方法

对之前答案的小修改:

使用cat,而不是更少。这样更快,而且不需要分页。 使用$1从第一个参数文件读取(如果存在)或$*从所有文件读取(如果存在)。如果这些变量为空,则从stdin读取(像cat一样) # !/bin/bash 猫$* |…

文件的方法

写入一个命名管道有点复杂,但这允许你把stdin(或文件)当作一个单独的文件:

使用mkfifo创建管道。 并行化写作过程。如果未读取命名管道,则可能阻塞。 要将stdin重定向到子进程(在这种情况下是必要的),使用<&0(与其他注释不同,这在这里不是可选的)。 # !/bin/bash mkfifo / tmp / myStream /tmp/myStream & #分离子进程(!) AddYourCommandHere /tmp/myStream #进程输入像一个文件, rm /tmp/myStream #正在清理

文件方法:变化

仅在没有给出参数的情况下创建命名管道。这对于从文件中读取可能更稳定,因为命名管道偶尔会阻塞。

#!/bin/bash
FILES=$*
if echo $FILES | egrep -v . >&/dev/null; then # if $FILES is empty
   mkfifo /tmp/myStream
   cat <&0 > /tmp/myStream &
   FILES=/tmp/myStream
fi
AddYourCommandHere $FILES     # do something ;)
if [ -e /tmp/myStream ]; then
   rm /tmp/myStream
fi

此外,它允许你迭代文件和stdin,而不是连接到一个单一的流:

for file in $FILES; do
    AddYourCommandHere $file
done

与…

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/bash
less <&0

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

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