没有参数传递时如何读取stdin?

aro*_*n23 11 bash stdin

当没有传递参数(文件)时我想使用标准输入时脚本不起作用.有没有办法在这段代码中使用stdin而不是文件?

我试过这个:

if [ ! -n $1 ] # check if argument exists
   then
   $1=$(</dev/stdin)  # if not use stdin as an argument
   fi

var="$1"
while read line
   do
   ...                # find the longest line
   done <"$var"
Run Code Online (Sandbox Code Playgroud)

Rya*_*yan 11

对于想要在缺少参数时从stdin读取值的一般情况,这将起作用.

$ echo param | script.sh
$ script.sh param
Run Code Online (Sandbox Code Playgroud)

script.sh

#!/bin/bash

set -- "${1:-$(</dev/stdin)}" "${@:2}"

echo $1
Run Code Online (Sandbox Code Playgroud)

  • set-$ {@:-$(&lt;/ dev / stdin)}`如果要从位置读取_all_参数,否则为stdin。(就像grep的行为一样。) (2认同)

pil*_*row 9

只需将bash特别解释/dev/stdin为文件名:

VAR=$1
while read blah; do
  ...
done < "${VAR:-/dev/stdin}"
Run Code Online (Sandbox Code Playgroud)

(请注意,如果为提供它的操作系统构建,bash实际上会使用该特殊文件 ,但是由于bash 2.04将在不支持它的系统上解决该文件的缺失.)/dev/stdin


mkl*_*nt0 6

pilcrow 的答案提供了一个优雅的解决方案这是对为什么 OP 的方法不起作用的解释。

OP 方法的主要问题是尝试使用分配位置参数$1,这是$1=...行不通的。

LHS 由 shell 扩展为的$1,并且结果被解释为要分配给的变量的名称 - 显然,而不是意图。

在 bash 中分配给的唯一方法$1set通过内置的. 需要注意的是,它set总是设置所有位置参数,因此您还必须包括其他参数(如果有)。

set -- "${1:-/dev/stdin}" "${@:2}"     # "${@:2}" expands to all remaining parameters
Run Code Online (Sandbox Code Playgroud)

(如果您期望最多只有1 个参数,set -- "${1:-/dev/stdin}"就可以了。)

上面还纠正了OP方法的第二个问题:尝试存储内容不是stdin中的文件名$1,因为<使用了。

${1:-/dev/stdin}是 bash参数扩展的一个应用程序,它表示:返回 的值$1,除非$1未定义(未传递任何参数)或其值为空字符串(""''已传递)。变体${1-/dev/stdin}(no :) 仅在未定义时才返回/dev/stdin$1如果包含任何值,即使是空字符串,也会返回)。

如果我们把它们放在一起:

# Default to filename '/dev/stdin' (stdin), if none was specified.
set -- "${1:-/dev/stdin}" "${@:2}"

while read -r line; do
   ...                # find the longest line
done < "$1"
Run Code Online (Sandbox Code Playgroud)

但是,当然,更简单的方法是${1:-/dev/stdin}直接用作文件名:

while read -r line; do
   ...                # find the longest line
done < "${1:-/dev/stdin}"
Run Code Online (Sandbox Code Playgroud)

或者,通过中间变量:

filename=${1:-/dev/stdin}
while read -r line; do
   ...                # find the longest line
done < "$filename"
Run Code Online (Sandbox Code Playgroud)