bash 不传递参数时如何读取标准输入?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19619490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read stdin when no arguments are passed?
提问by aron23
Script doesn't work when I want to use standard input when there are no arguments (files) passed. Is there any way how to use stdin instead of a file in this code?
当我想在没有传递参数(文件)的情况下使用标准输入时,脚本不起作用。有什么办法可以在这段代码中使用stdin而不是文件吗?
I tried this:
我试过这个:
if [ ! -n ] # check if argument exists
then
=$(</dev/stdin) # if not use stdin as an argument
fi
var=""
while read line
do
... # find the longest line
done <"$var"
采纳答案by pilcrow
Just substitute bash's specially interpreted /dev/stdin
as the filename:
只需替换特别解释/dev/stdin
为文件名的bash :
VAR=
while read blah; do
...
done < "${VAR:-/dev/stdin}"
(Note that bash will actually use that special file/dev/stdin
if built for an OS that offers it, but since bash 2.04 will work around that file's absence on systems that do not support it.)
(请注意,如果为提供它的操作系统构建,bash 实际上将使用该特殊文件,但由于 bash 2.04 将在不支持它的系统上解决该文件缺失的问题。)/dev/stdin
回答by Ryan
For a general case of wanting to read a value from stdin when a parameter is missing, this will work.
对于在缺少参数时想要从 stdin 读取值的一般情况,这将起作用。
$ echo param | script.sh
$ script.sh param
script.sh
脚本文件
#!/bin/bash
set -- "${1:-$(</dev/stdin)}" "${@:2}"
echo
回答by mklement0
pilcrow's answerprovides an elegant solution; this is an explanation of why the OP's approach didn't work.
pilcrow 的回答提供了一个优雅的解决方案;这是对为什么 OP 的方法不起作用的解释。
The main problem with the OP's approachwas the attempt to assign topositional parameter $1
with $1=...
, which won't work.
主要与OP的做法的问题是要尝试分配给位置参数$1
有$1=...
,这是行不通的。
The LHS is expanded by the shell to the valueof $1
, and the resultis interpreted as the name of the variable to assign to - clearly, not the intent.
LHS由shell来扩展价值的$1
,并且结果被解释为变量的名称,分配到-显然,并不是意图。
The only way to assign to $1
in bash is via the set
builtin.
The caveat is that set
invariably sets allpositional parameters, so you have to include the other ones as well, if any.
在 bash 中分配给$1
set
的唯一方法是通过内置的. 需要注意的是,set
总是设置所有位置参数,因此您必须包括其他参数(如果有)。
set -- "${1:-/dev/stdin}" "${@:2}" # "${@:2}" expands to all remaining parameters
(If you expect only at most 1argument, set -- "${1:-/dev/stdin}"
will do.)
(如果您期望最多只有1 个参数,set -- "${1:-/dev/stdin}"
则可以。)
The above also corrects a secondary problem with the OP's approach: the attempt to store the contentsrather than the filenameof stdin in $1
, since <
is used.
以上还纠正了 OP 方法的一个次要问题:尝试在 中存储内容而不是stdin的文件名$1
,因为<
使用了。
${1:-/dev/stdin}
is an application of bash parameter expansionthat says: return the value of $1
, unless $1
is undefined (no argument was passed) or its value is the empty string (""
or ''
was passed). The variation ${1-/dev/stdin}
(no :
) would only return /dev/stdin
if $1
is undefined(if it contains anyvalue, even the empty string, it would be returned).
${1:-/dev/stdin}
是 bash参数扩展的应用程序,它说:返回 , 的值$1
,除非$1
未定义(未传递参数)或其值为空字符串(""
或''
已传递)。变化${1-/dev/stdin}
(无:
)将只返回/dev/stdin
如果$1
是不确定的(如果它包含任何值,甚至空字符串,它会被退回)。
If we put it all together:
如果我们把它们放在一起:
# 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 < ""
But, of course, the much simpler approach would be to use ${1:-/dev/stdin}
as the filename directly:
但是,当然,更简单的方法是${1:-/dev/stdin}
直接用作文件名:
while read -r line; do
... # find the longest line
done < "${1:-/dev/stdin}"
or, via an intermediate variable:
或者,通过中间变量:
filename=${1:-/dev/stdin}
while read -r line; do
... # find the longest line
done < "$filename"
回答by kenorb
Here is my version of script:
这是我的脚本版本:
#!/bin/bash
file=${1--} # POSIX-compliant; ${1:--} can be used either.
while IFS= read -r line; do
printf '%s\n' "$line"
done < <(cat -- "$file")
If file is not present in the argument, read the from standard input.
如果参数中不存在文件,则从标准输入中读取。
See more examples: How to read from file or stdin in bash?at stackoverflow SE
查看更多示例:如何在 bash 中读取文件或标准输入?在 stackoverflow SE
回答by Oswald
Variables are assigned a value by Var=Value
and that variable is used by e.g. echo $Var
. In your case, that would amount to
变量被赋值,Var=Value
并且该变量被例如使用echo $Var
。在你的情况下,这相当于
1=$(</dev/stdin)
when assigning the standard input. However, I do not think that variable names are allowed to start with a digit character. See the question bash read from file or stdinfor ways to solve this.
分配标准输入时。但是,我认为不允许变量名以数字字符开头。有关解决此问题的方法,请参阅问题bash 从文件或标准输入读取。