标签: process-substitution

进程替换捕获stderr

我将使用这个问题grep,因为它的用法文本打印到stderr

$ grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Run Code Online (Sandbox Code Playgroud)

您可以使用流程替换轻松捕获stdout

$ read b < <(echo hello world)
Run Code Online (Sandbox Code Playgroud)

然而,stderr滑过进程替换并打印到控制台

$ read b < <(grep)
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Run Code Online (Sandbox Code Playgroud)

我想使用进程替换来捕获stderr.我现在正在使用它

$ grep 2> log.txt

$ read b < log.txt
Run Code Online (Sandbox Code Playgroud)

但我希望避免临时文件.

bash stderr process-substitution

6
推荐指数
1
解决办法
2044
查看次数

bash"wc -l"命令输出在呼叫或通过tee时有所不同

当我在Bash中发出两个等效命令时,我得到了不同的输出(来自"wc -l"命令),见下文:

root@devel:~# ls /usr/bin -lha | tee >(wc -l) >(head) > /dev/null
total 76M
drwxr-xr-x  2 root root      20K Nov 11 18:58 .
drwxr-xr-x 10 root root     4.0K Oct  8 15:31 ..
-rwxr-xr-x  1 root root      51K Feb 22  2017 [
-rwxr-xr-x  1 root root       96 Jan 19  2017 2to3-3.5
-rwxr-xr-x  1 root root      23K Mar 22  2017 addpart
lrwxrwxrwx  1 root root       26 May 10  2017 addr2line -> x86_64-linux-gnu-    addr2line
lrwxrwxrwx  1 root root        6 Dec 13  2016 …
Run Code Online (Sandbox Code Playgroud)

bash tee wc process-substitution

6
推荐指数
1
解决办法
430
查看次数

有些程序不接受输入文件的进程替换吗?

我正在尝试将进程替换用于程序的输入文件,但它无法正常工作.是因为某些程序不允许输入文件的进程替换吗?

以下不起作用:

bash -c "cat meaningless_name"
    >sequence1
    gattacagattacagattacagattacagattacagattacagattacagattaca
    >sequence2
    gattacagattacagattacagattacagattacagattacagattacagattaca
bash -c "clustalw -align -infile=<(cat meaningless_name) -outfile=output_alignment.aln -newtree=output_tree.dnd"
    (Less verbose output, finishing with:
    No sequences in file. No alignment!
Run Code Online (Sandbox Code Playgroud)

但以下控件确实有效:

bash -c "clustalw -align -infile=meaningless_name -outfile=output_alignment.aln -newtree=output_tree.dnd"
    (Verbose output, finishing with:
    CLUSTAL-Alignment file created  [output_alignment.aln]
bash -c "cat <(cat meaningless_name) > meaningless_name2"
diff meaningless_name meaningless_name2
    (No output: the two files are the same)
bash -c "clustalw -align -infile=meaningless_name2 -outfile=output_alignment.aln -newtree=output_tree.dnd"
    (Verbose output, finishing with:
    CLUSTAL-Alignment file created  [output_alignment.aln]
Run Code Online (Sandbox Code Playgroud)

这表明进程替换本身有效,但clustalw程序本身不喜欢进程替换 - …

unix bash ipc process-substitution

5
推荐指数
2
解决办法
650
查看次数

bash:如何确保与 exec 一起使用的进程替换终止?

如果我跑

$#/bin/bash
for i in `seq 5`; do
    exec 3> >(sed -e "s/^/$i: /"; echo "$i-")
    echo foo >&3
    echo bar >&3
    exec 3>&-
done
Run Code Online (Sandbox Code Playgroud)

那么结果是不同步的;它可能是这样的:

1: foo
1: bar
2: foo
2: bar
1-
3: foo
3: bar
2-
3-
4: foo
5: foo
4: bar
5: bar
4-
5-
Run Code Online (Sandbox Code Playgroud)

>(...)在进行下一次迭代之前,如何确保流程替换已完成?

sleep 0.1exec 3>&-帮助之后插入,但它不优雅,效率低下,并且不能保证总是有效。

编辑:这个例子可能看起来很傻,但它只是为了说明。我正在做的是在循环中读取输入流,将每一行提供给一个在循环中偶尔会改变的进程。在代码中更容易解释:

# again, simplified for illustration
while IFS= read line; do
    case $line in
    @*)
        exec 3>&-
        filename=${line:1}
        echo "starting $filename" …
Run Code Online (Sandbox Code Playgroud)

bash process-substitution

5
推荐指数
2
解决办法
1814
查看次数

使用bash进程替换拒绝文件描述符权限?

我有一个bash脚本,我想在标准输出中与用户通信,但也通过文件描述符将命令发送到子进程 - 如下所示:

# ...
# ...

echo "Hello user, behold a cleared gnuplot window"

# pass the string "clear" to gnuplot via file descriptor 3
echo "clear" >&3  
Run Code Online (Sandbox Code Playgroud)

所以我认为我可以通过首先启动子进程来"设置它":

#!/bin/bash

# Initiate(?) file descriptor 3, and let it direct to a newly 
# started gnuplot process:
exec >3 >( gnuplot )
Run Code Online (Sandbox Code Playgroud)

但这会产生错误:

/dev/fd/63: Permission denied
Run Code Online (Sandbox Code Playgroud)

这是预期的吗?

我不明白发生了什么.(我做错了什么?可能是我的系统有一些特殊的安全设置,不允许我正在尝试做什么?(运行Ubuntu Linux 12.10.))

"解决方法" - 以下似乎与我正在尝试的内容相同,并且可以正常工作:

#!/bin/bash

# open fd 3 and direct to where fd 1 directs to, i.e. std-out 
exec 3>&1 …
Run Code Online (Sandbox Code Playgroud)

bash file-descriptor permission-denied process-substitution

5
推荐指数
1
解决办法
3254
查看次数

进程替换为grep缺少预期输出

假设我有一个程序输出:

abcd
l33t
1234
Run Code Online (Sandbox Code Playgroud)

我会用它来模拟printf 'abcd\nl33t\n1234\n'.我想同时将这个输出提供给两个程序.我的想法是使用进程替换tee.假设我想将输出的副本提供给grep:

printf 'abcd\nl33t\n1234\n' | tee >(grep '[a-z]' >&2) | grep '[0-9]'
Run Code Online (Sandbox Code Playgroud)

我使用Bash 4.1.2(Linux,CentOS 6.5)得到以下内容,这很好:

l33t
1234
abcd
l33t
Run Code Online (Sandbox Code Playgroud)

但是如果进程替换没有被重定向到stderr(即没有>&2),就像这样:

printf 'abcd\nl33t\n1234\n' | tee >(grep '[a-z]') | grep '[0-9]'
Run Code Online (Sandbox Code Playgroud)

然后我得到:

l33t
1234
l33t
Run Code Online (Sandbox Code Playgroud)

这就像进程替换的stdout(第一个grep)被管道(第二个grep)之后的进程使用.除了第二个grep已经自己读取东西,所以我想它不应该考虑第一个grep中的东西.除非我弄错了(我肯定是).

我错过了什么?

bash pipeline io-redirection process-substitution

5
推荐指数
1
解决办法
328
查看次数

Bash:进程替换的范围是什么?

据我所知,进程替换 <(...) / >(...) 创建了 fd

并将括号中的命令输出存储到生成的 fd 中。

因此,这两个命令是等价的

$ ls -al
$ cat <(ls -al)
Run Code Online (Sandbox Code Playgroud)

在这里,我的问题是,生成的文件描述符保留多长时间?

我读过这篇文章,但似乎我的理解是错误的。

如果进程替换被扩展为函数的参数,在调用函数期间扩展为环境变量,或扩展为函数内的任何赋值,则进程替换将“保持打开”以供函数内的任何命令使用或者它的被调用者,直到设置它的函数返回。如果在被调用者中再次设置相同的变量,除非新变量是本地变量,否则先前的进程替换将关闭并且在被调用者返回时对调用者不可用。

本质上,在函数内扩展为变量的进程替换保持打开状态,直到发生进程替换的函数返回——即使分配给由函数调用者设置的局部变量。动态范围不会保护它们免于关闭。

我最好的猜测是,在阅读之后,创建的 fd 在被使用之前不会被关闭。

由此,我写了一个非常愚蠢的代码,如下所示

#!/bin/bash

test_subs () {
  echo "Inside a function"
  FD2=<(ls -al)

  cat $FD1
  cat $FD2
}
FD1=<(ls -al)
test_subs

Result======================================
Inside a function
cat: /dev/fd/63: No such file or directory
cat: /dev/fd/63: No such file or directory
Run Code Online (Sandbox Code Playgroud)

似乎新打开的 fd 在一行命令运行后立即关闭。

生成的fd维持多久,那么进程替换的范围是什么?

bash process-substitution

5
推荐指数
1
解决办法
485
查看次数

使用进程替换 - 仅将stderr发送到文件

出于某种原因,似乎stderr在以下bash脚本中被发送到stdout:

exec > >( while read line; do echo " stdout: $line"; done )
exec 2> >( while read line; do echo " stderr: $line"; done )

echo "rolo"
echo "cholo" >&2
Run Code Online (Sandbox Code Playgroud)

如果你运行它,输出是这样的:

stdout:rolo
stdout:stderr:cholo

有谁知道为什么会这样?据我所知,发生的事情是stderr被发送到stdout,这就是为什么第一行是从第二行捕获输出的原因?

bash shell io-redirection process-substitution

5
推荐指数
1
解决办法
123
查看次数

模拟"命名"流程替换

假设我有一个大的gzip压缩文件data.txt.gz,但通常需要将ungzipped版本提供给程序.当然,不是创建独立解压缩,而是data.txt可以使用进程替换语法:

./program <(zcat data.txt.gz)

但是,根据具体情况,这可能很烦人且容易出错.

有没有办法模拟命名的进程替换?也就是说,创建一个伪文件data.txt,zcat data.txt.gz只要访问它就会"展开"到进程替换中.与符号链接不同,将读取操作转发到另一个文件,但在这种情况下,它需要是临时命名管道.

谢谢.

PS.有点类似的问题


编辑(来自评论)实际的用例是拥有一个大型的gzip语料库,除了以原始形式使用外,还有时需要通过一系列轻量级操作(标记化,小写等)进行处理,然后输入到一些"更重"的代码.存储预处理的副本会浪费磁盘空间并重复重新输入完​​整的预处理管道可能会引入错误.同时,在运行中运行管道会产生很小的计算开销,因此需要一个长期存在的伪文件来隐藏详细信息.

unix bash named-pipes process-substitution

4
推荐指数
1
解决办法
81
查看次数

处理每个数组条目的替换,没有评估

我有一个任意字符串数组,例如a=(1st "2nd string" $'3rd\nstring\n' ...).
我想将这些字符串传递给将其参数解释为文件的命令,例如paste.

对于固定数量的变量,我们可以使用流程替换

paste <(printf %s "$var1") <(printf %s "$var2") <(printf %s "$var3")
Run Code Online (Sandbox Code Playgroud)

但这只有在事先知道变量数量的情况下才有效。
对于数组a,我们可以写一些相当安全的东西,比如

eval paste $(printf '<(printf %%s %q) ' "${a[@]}")
Run Code Online (Sandbox Code Playgroud)

出于兴趣:有没有办法在a不使用的情况下处理替换每个条目eval?请记住,a的条目可以包含任何字符(除了\0因为bash不支持它)。

arrays bash process-substitution

4
推荐指数
2
解决办法
224
查看次数