下面的Perl脚本(my.pl)既可以从命令行参数中的文件读取,也可以从标准输入(STDIN)读取:
while (<>) {
print($_);
}
Perl my.pl将从标准输入中读取,而Perl my.pl .txt将从a.txt中读取。这很方便。
Bash中也有类似的功能吗?
下面的Perl脚本(my.pl)既可以从命令行参数中的文件读取,也可以从标准输入(STDIN)读取:
while (<>) {
print($_);
}
Perl my.pl将从标准输入中读取,而Perl my.pl .txt将从a.txt中读取。这很方便。
Bash中也有类似的功能吗?
当前回答
从stdin读入变量或从文件读入变量。
现有答案中的大多数示例使用循环,当它从stdin读取时立即回显每一行。这可能不是你真正想做的。
在许多情况下,您需要编写一个脚本来调用只接受file参数的命令。但是在你的脚本中,你可能也想要支持stdin。在这种情况下,您需要首先读取完整的stdin,然后将其作为文件提供。
让我们看一个例子。下面的脚本打印一个证书的证书详细信息(以PEM格式),该证书可以作为文件传递,也可以通过stdin传递。
# print-cert script
content=""
while read line
do
content="$content$line\n"
done < "${1:-/dev/stdin}"
# Remove the last newline appended in the above loop
content=${content%\\n}
# Keytool accepts certificate only via a file, but in our script we fix this.
keytool -printcert -v -file <(echo -e $content)
# Read from file
cert-print mycert.crt
# Owner: CN=....
# Issuer: ....
# ....
# Or read from stdin (by pasting)
cert-print
#..paste the cert here and press enter
# Ctl-D
# Owner: CN=....
# Issuer: ....
# ....
# Or read from stdin by piping to another command (which just prints the cert(s) ). In this case we use openssl to fetch directly from a site and then print its info.
echo "" | openssl s_client -connect www.google.com:443 -prexit 2>/dev/null \
| sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' \
| cert-print
# Owner: CN=....
# Issuer: ....
# ....
其他回答
每当IFS中断输入流时,回显解决方案就添加新行。@fgm的回答可以稍微修改一下:
cat "${1:-/dev/stdin}" > "${2:-/dev/stdout}"
#!/usr/bin/bash
if [ -p /dev/stdin ]; then
#for FILE in "$@" /dev/stdin
for FILE in /dev/stdin
do
while IFS= read -r LINE
do
echo "$@" "$LINE" #print line argument and stdin
done < "$FILE"
done
else
printf "[ -p /dev/stdin ] is false\n"
#dosomething
fi
运行:
echo var var2 | bash std.sh
结果:
var var2
运行:
bash std.sh < <(cat /etc/passwd)
结果:
root:x:0:0::/root:/usr/bin/bash
bin:x:1:1::/:/usr/bin/nologin
daemon:x:2:2::/:/usr/bin/nologin
mail:x:8:12::/var/spool/mail:/usr/bin/nologin
也许最简单的解决方案是使用合并重定向操作符重定向标准输入:
#!/bin/bash
less <&0
标准输入是文件描述符0。上面的代码将通过管道传输到bash脚本的输入发送到less的标准输入中。
阅读有关文件描述符重定向的更多信息。
与…
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
以下是使用标准sh(在Debian上用Dash测试)的工作,相当可读,但这是一个品味问题:
if [ -n "$1" ]; then
cat "$1"
else
cat
fi | commands_and_transformations
详细信息:如果第一个参数非空,则cat该文件,否则cat标准输入。然后整个if语句的输出由command_and_transforms处理。