通常我们只需要传递一个参数:
echo abc | cat
echo abc | cat some_file -
echo abc | cat - some_file
有没有办法传递两个参数?比如
{echo abc , echo xyz} | cat
cat `echo abc` `echo xyz`
我可以先将两个结果都存储在一个文件中
echo abc > file1
echo xyz > file2
cat file1 file2
但这样我可能会意外覆盖文件,这是不行的。这会进入一个非交互式脚本。基本上,我需要一种方法来传递两个任意命令的结果,而cat
无需写入文件。
更新:抱歉,示例掩盖了问题。虽然{ echo abc ; echo xyz ; } | cat
似乎有效,但输出是由于echo
s 而不是cat
。
一个更好的例子是{ cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,
它没有按预期工作。
和
file1:
a,b
c,d
file2:
1,2
3,4
预期输出为:
b,1
d,3
解决:
使用流程替代:cat <(command1) <(command2)
或者,使用以下命令创建命名管道mkfifo
:
mkfifo temp1
mkfifo temp2
command1 > temp1 &
command2 > temp2 &
cat temp1 temp2
不太优雅且更冗长,但可以正常工作,只要您确保 temp1 和 temp2 事先不存在。
答案1
我认为你想要“流程替代”http://tldp.org/LDP/abs/html/process-sub.html。它也适用于 zsh,尽管它有更多选项并且语法可能不同。
它为每个替换创建一个伪文件 ( /dev/fd/something
)。它非常有用。该命令只能以流的形式读取,这意味着它不能使用 fseek 来回移动。它需要将其作为字节流读取,就像管道一样。
您的示例可作为流程替代:
cat <(echo abc) <(echo xyz)
paste -d, <(cut -f2 -d, file1) <(cut -f1 -d, file2)
将其视为一种使用进程的工具,并让其假装是一个没有任何临时文件的文件。
(从我的先前的答案)
答案2
我喜欢 xargs 例如我想找到 /usr/local 下所有 mysql 数据目录的大小
osx:本地用户$ pwd /usr/本地 osx:本地用户$ ls | grep mysql mysql mysql-5.0.51a-osx10.5-x86_64 mysql-5.0.51b-osx10.5-x86_64 mysql-5.1.39-osx10.5-x86_64 mysql-5.6.17-osx10.7-x86_64 os x:本地用户$ ls | grep mysql | sudo xargs du -sh 4.0K mysql 2.8G mysql-5.0.51a-osx10.5-x86_64 10G mysql-5.0.51b-osx10.5-x86_64 25G mysql-5.1.39-osx10.5-x86_64 753M mysql-5.6.17-osx10.7-x86_64 osx:本地用户$
答案3
花括号确实起作用了,因为管道运算符会将分组命令的标准输出连接到第三个命令的标准输入。
您可以通过运行任何不使用标准输入的命令来判断打印输出不是来自回声,例如,{ echo 1; echo 2;} | echo 3
将打印 3 而不是 1\n2\n3。
但是,这并不是您想要的结果,因为花括号中的两个命令写入相同的输出,就像cat
对其结果执行 -ing 操作一样。要生成两个不同的结果以用作命令的两个参数paste
,您必须使用临时文件或命名管道。
您可以使用mktemp
它来生成唯一的临时文件或mkfifo
创建FIFO管道文件。
答案4
我发现了一种很棒的通用方法来并行化输入流并使用流融合:
while IFS= read -r -u3 three \
&& IFS= read -r -u4 four \
&& IFS= read -r -u5 five
do echo "three=$three, four=$four, five=$five"
done 3< <( firstCommand ) \
4< <( secondCommand ) \
5< <( thirdCommand )
只要有可用的流和文件描述符,就可以扩展它。末尾的斜线只是为了避免换行符,从而将一行扩展到多行,以使其更容易被阅读。
它的工作原理如下:
- 命令被放在进程替换 (
<( … )
) 中,因此它们显示为文件,使用隐式先进先出秒。 - 这些文件使用新流发送到命令(
… N< …
,其中否是流的编号)。 - 现在这里,我使用
while
循环作为命令。 - 只要所有(
&&
)命令read
都还未到达EOF并被释放,它就会循环。 - 那些
read
s 被告知不要对转义进行任何特殊处理(-r
),不要切断任何东西(IFS=
),从特定流中读取一行(-uN
),并将其放入特定变量中(例如three
)。 - 最后,实际的命令(
echo
在本例中为)可以通过随意使用多个变量,对多个流进行操作。
我觉得有些步骤可能会被跳过,所以如果有人知道怎么做没有减少任何由于此示例的灵活性和强大功能,欢迎您在下面编辑此答案或评论。