这个shell语法的机制:$ {1: - $(</ dev/stdin)}

Joe*_*ley 9 bash stdin command-substitution parameter-expansion

我最近遇到了这个非常简洁的语法,在创建bash可以接受来自STDIN的参数或流的函数的上下文中(即可以通过管道传递).从表面上看,我理解这里发生了什么,但我想更多地解释一下这是如何工作的实际机制.

这是语法(根据标题): ${1:-$(</dev/stdin)}

在上下文中,可以将其用作:

log(){
 echo -e >&1 "INFO: ${1:-$(</dev/stdin)}"
}
Run Code Online (Sandbox Code Playgroud)

允许以下用法:

$ log foo
INFO: foo
Run Code Online (Sandbox Code Playgroud)

或者,您也可以这样做

mv -v foo.ext bar.ext | log
INFO: renamed 'foo.ext' -> 'bar.ext'
Run Code Online (Sandbox Code Playgroud)

这很棒,因为它是我看到的用于启用参数和管道功能的单一最简洁的方法bash(不幸的是我忘记了我现在遇到它的地方).

现在,我理解(或者我认为我理解),这里发生的大部分事情至少表面上看,但我会更加理解.这是我如何解释它,然后是我剩下的问题:

${1:-$(</dev/stdin)}

  • ${1} 显然是函数接受的默认参数
  • ${1:-x}是否为变量/大括号扩展'后退'到字符串'x',$1否则为空(或未设置?).在这种情况下,回退到STDIN进程子.
  • $()显然是一个进程命令替换
  • 最后,</dev/stdin显然是标准输入的重定向,它允许管道工作.

这基本上说如果$1不是由参数填充,则回退到使用STDIN - 我在概念上很满意.

所以这是我的问题:

  1. 我从来没有<进程命令替换中看到redirect(),没有在它之前的实际命令(例如$(cat < somefile.ext)).那么当进程命令替换收到重定向而没有其他命令要调用时,实际发生了什么(细节)?
  2. 为什么有必要在进程命令替换中包装STDIN重定向?(实际上,当我写这个时,它发生在我身上,我没有测试它,但我会保持简单).
  3. 这样安全吗?我已经将它与多线STDIN一起使用了,到目前为止还没有破坏.这可能会降到哪里(如果在哪里?).

Nah*_*eul 5

  1. $(.. ):从bash的手册是命令替换不处理substiution <(.. ).并从命令替换

命令替换$(cat文件)可以用等效但更快的$(<file)替换.

  1. /dev/stdin是一个符号链接/proc/self/fd/0,方便这里因为$(<.. )语法需要一个文件.

  2. 这可能会导致问题,因为命令可能会被阻止,直到stdin关闭.它是安全的意思是多线输入将被保留,因为au双引号.

最后,mv -v foo.ext bar.ext | log为每个日志命令创建管道并分叉进程(如in )可能是无效的.