我经常想将相对较短的字符串数据(尽管可能是几行)馈送到命令行程序,这些程序仅以重复的方式仅接受来自文件(例如wdiff)的输入。当然,我可以创建一个或多个临时文件,将字符串保存在那里,然后以文件名作为参数运行命令。但是在我看来,如果将数据实际写入磁盘,此过程似乎效率很低,而且如果我多次重复此过程,例如对磁盘的损害可能会严重损害磁盘。如果我想将长文本文件的单行输入wdiff。有没有建议的方法来避免这种情况,例如使用伪文件(例如管道)来临时存储数据,而无需实际将其写入磁盘(或仅在超过临界长度时才将其写入)。请注意,wdiff具有两个参数,据我所知,将无法像wdiff <"text"这样来馈送数据。

评论

可以通过xargs解决吗?

不知道,但是对我来说,怎么做并不明显。据我了解,xargs将从命令的文件字符串参数组成输入行。但是我需要相反的情况。

@rahmu我看了一下,但是我认为那里的问题设置有些不同。至少我看不出答案会有什么帮助。我不希望避免的是正确生成临时文件的答案,如果没有,实际上是某种缓冲实际上阻止了写文件。我对临时文件的工作方式了解有限!

echo $ data_are_here有什么问题| dumb_program?

这将仅支持一个输入文件,并非所有程序都将从stdin中读取。

#1 楼

使用命名管道。通过说明的方式:

mkfifo fifo
echo -e "hello world\nnext line\nline 3" > fifo


-e告诉echo正确解释换行符(\n)。这将阻塞,即您的外壳将挂起,直到有人从管道读取数据为止。

在同一目录中的某个位置打开另一个外壳:

cat fifo


您将阅读echo,它将释放另一个shell。尽管管道作为磁盘上的文件节点存在,但通过管道的数据却不存在。这一切都发生在内存中。您可以为回声提供背景(&)。

管道具有64k缓冲区(在Linux上),并且像套接字一样,在充满时将阻止编写器,因此只要您不丢失数据不要过早地杀死作家。

评论


好的,谢谢,这也适用于两个命名管道和wdiff。但是我想了解的是,有一定(少量)的内存可用于管道作为缓冲区。如果我超过缓冲区大小会怎样?

–highsciguy
13年2月6日在11:57

我添加了关于该问题的最后一段。

–金锁
13年2月6日在12:19

/ tmp在大多数发行版中都配置为使用RAM中的tmpfs文件系统。当您在/ tmp中写入文件时,它将直接进入RAM,这对于必须快速访问并多次重写的半弹性文件是一个很好的答案。

–user21228
13年2月7日在9:57

#2 楼

在Bash中,您可以使用command1 <( command0 )重定向语法,该语法将command0的stdout重定向并将其传递到以文件名作为命令行参数的command1。这称为进程替换。
一些使用文件名命令行参数的程序实际上需要一个真正的随机访问文件,因此该技术不适用于那些文件。但是,它可以与wdiff一起正常工作:
user@host:/path$ wdiff <( echo hello; echo hello1 ) <( echo hello; echo hello2 )
hello
[-hello1-]
{+hello2+}

在后台,这将创建FIFO,将<( )内部的命令通过管道传递给FIFO,并将FIFO的文件描述符作为参数传递。若要查看发生了什么,请尝试将其与echo一起使用以打印自变量而不进行任何操作:
user@host:/path$ echo <( echo hello )
/dev/fd/63

创建命名管道更为灵活(如果要使用多个过程编写复杂的重定向逻辑) ,但对于许多用途而言,这已经足够了,并且显然更易于使用。
当您要将其用作输出时,还有>( )语法,例如
$ someprogram --logfile >( gzip > out.log.gz )

另请参阅bash man页面的“过程替换”部分和有关相关技术的Bash重定向备忘单。

评论


KSH不支持此功能

–chanchal1987
2014年7月3日在9:58

ksh发明了这个。您正在使用不支持它的ksh变体

–尼尔·麦圭根(Neil McGuigan)
16年7月31日在1:28

一些带有文件名命令行参数的程序实际上需要一个真正的随机访问文件,因此该技术不适用于那些文件。在这些情况下您会怎么做。例如,ssh -F <(vagrant ssh-config)默认会很好,但是可惜。

– Sukima
17年11月9日在22:44



#3 楼

wdiff是一种特殊情况,因为它需要2个文件名参数,但是对于仅需要1个参数并且固执地拒绝接受文件名参数以外的所有命令的命令,有2个选项:



文件名“-”(即减号)的有效时间约为1/2。它似乎取决于所讨论的命令以及该命令的开发人员是否捕获这种情况并按预期进行处理。例如


$> ls | cat-



Linux中存在一个名为/ dev / stdin的伪文件,可以在命令绝对需要文件名的情况下使用该伪文件。因为它不需要命令中的任何特殊文件名处理,所以这更有可能起作用。如果fifo有效,或者bash进程替换方法有效,则这也应该有效,并且不是特定于shell的。例如


$> ls |猫/ dev / stdin




评论


更少和openssl像/ dev / stdin,而不是/ dev / fd / NUM :-)

–鳗鱼ghEEz
16年4月30日在0:04