pilcrow's answer 提供了一种优雅的解决方案;这是对为什么OP的方法不起作用的解释。
OP的方法的主要问题是尝试使用$1=...
将值赋给位置参数$1
,但这并不起作用。
Shell会将LHS扩展为$1
的值,并将结果解释为要分配的变量的名称 - 显然,这不是意图。
在bash中分配$1
的唯一方法是通过set
内置命令。但有一个警告:无论如何,set
都会设置所有位置参数,因此如果有其他参数,您也必须包括它们。
set -- "${1:-/dev/stdin}" "${@:2}"
如果你只期望最多一个参数,
set -- "${1:-/dev/stdin}"
将会起作用。
上述方法还纠正了 OP 的方法中的一个次要问题:尝试存储标准输入流的内容而不是文件名到
$1
中,因为使用了
<
。
${1:-/dev/stdin}
是 bash
参数扩展 的应用,它表示:返回
$1
的值,除非
$1
未定义(没有传递参数)或其值为空字符串(传递了
""
或
''
)。变量
${1-/dev/stdin}
(没有
:
)只有在
$1
未定义时才会返回
/dev/stdin
(如果它包含任何值,即使是空字符串,也会被返回)。
将所有内容组合起来:
set -- "${1:-/dev/stdin}" "${@:2}"
while read -r line; do
...
done < "$1"
当然,更简单的方法是直接使用${1:-/dev/stdin}
作为文件名:
while read -r line; do
...
done < "${1:-/dev/stdin}"
或者,通过一个中间变量:
filename=${1:-/dev/stdin}
while read -r line; do
...
done < "$filename"