重定向的奇怪语法

时间:2015-02-01 04:09:34

标签: bash pipe named-pipes pipeline io-redirection

我在浏览this问题时遇到了以下脚本:

rm -f out
mkfifo out
trap "rm -f out" EXIT
while true
do
  cat out | nc -l 1500 > >( # parse the netcat output, to build the answer redirected to the pipe "out".
    export REQUEST=
    while read line
    do
      line=$(echo "$line" | tr -d '[\r\n]')

      if echo "$line" | grep -qE '^GET /' # if line starts with "GET /"
      then
        REQUEST=$(echo "$line" | cut -d ' ' -f2) # extract the request
      elif [ "x$line" = x ] # empty line / end of request
      then
        HTTP_200="HTTP/1.1 200 OK"
        HTTP_LOCATION="Location:"
        HTTP_404="HTTP/1.1 404 Not Found"
        # call a script here
        # Note: REQUEST is exported, so the script can parse it (to answer 200/403/404 status code + content)
        if echo $REQUEST | grep -qE '^/echo/'
        then
            printf "%s\n%s %s\n\n%s\n" "$HTTP_200" "$HTTP_LOCATION" $REQUEST ${REQUEST#"/echo/"} > out
        elif echo $REQUEST | grep -qE '^/date'
        then
            date > out
        elif echo $REQUEST | grep -qE '^/stats'
        then
            vmstat -S M > out
        elif echo $REQUEST | grep -qE '^/net'
        then
            ifconfig > out
        else
            printf "%s\n%s %s\n\n%s\n" "$HTTP_404" "$HTTP_LOCATION" $REQUEST "Resource $REQUEST NOT FOUND!" > out
        fi
      fi
    done
  )
done

然而,我仍在努力“解码”第6行中的语法,即:> >

一方面,我希望>个字符之间没有任何空格 - 只要删除该空白区域,脚本就不再运行了。

另一方面,我不希望找到重定向发送到另一个进程,因为在这种情况下,简单的管道将是完美的选择。实际上,我将> >替换为|,脚本运行顺利。

长话短说,你能解释一下:

  1. 为什么中间的空格>强制性的?
  2. 这是命令的语义> > ? (我猜是重定向!)
  3. 为什么不使用管道而不是重定向?
  4. 提前谢谢。

1 个答案:

答案 0 :(得分:3)

语法不是> >,而是> >()。那是process substitution。基本上bash在管道内的进程上创建一个带有标准输入的命名管道,可以有效地作为外部进程的文件。

任何被重定向到管道的内容都将被管道内的进程读取为标准输入。在您的情况下,该进程本身就是一个多行bash脚本。

如果用管道替换> >,你的脚本将大致相同,但你有点作弊。同样,实际语法不是> >,而是> >(),因此当您将其更改为| ()时,您实际上会使用明确的子shell(括号内的部分)。没有那个子shell,你有

cat out | nc -l 1500 | export REQUEST=
    ...

export不读取标准输入,并且脚本的其余部分不会成为管道的一部分,因此它的行为不会一致。