如何将字符发送到命令,就像它们来自文件一样?


22

如何将字符发送到命令,就像它们来自文件一样?

例如,我尝试过:

wc < "apple pear orange"
-bash: apple pear orange: No such file or directory

Answers:



18

另两种方法(无需额外的努力即可进行多行输入):

  1. 使用“此处文档”:

    $ wc << EOF
    苹果梨橙
    紧急行动
      1 3 18
    $

    EOF字符串是一个定界符。您可以使用任何字符串;EOF只是常规选择。

  2. 使用tty作为输入:

    $ wc
    苹果梨橙
    Ctrl+D
      1 3 18
    $

    这样做的缺点是,只要键入名称,该程序便会开始运行并开始读取输入。这可能令人不安;例如:

    $ grep v
    快速的棕色狐狸              (打字) 
    跳过                       (打字) 
    跳过                       (这是grep的输出!) 
    懒狗。                   (输入)
    Ctrl + D
                                    (此处无输出) 
    $

记录:<<<表单还允许多行输入而无需额外的努力,因为- "封闭的字符串可以包含换行符。当然,<< EOF如果您有多行输入,则表格(原始的here-doc语法)更易于阅读。
Alexis

手册页说,这里的字符串语法是<<< word-当然,在外壳程序上下文中,a word可以是带引号的字符串,包含空格和换行符!天哪!这是如此明显,以至于不言而喻(实际上,我在手册页中根本没有提到它)。:-(感谢您向我指出!
G-Man说'Resstate Monica''Jan

实际上,我不会将其称为简单或显而易见。word在手册页中将A 定义为“被shell视为单个单元的字符序列”(也称为“令牌”),并且您需要知道引用的字符串在相关意义上被视为“单个单元”(反斜线处理,变扩建等。”但事实上这就是双引号的外壳全部目的(单引号也从扩大保护。)外壳的处理模式是非常深思熟虑,并且一点也不简单。
亚历克西斯

@alexis:当我像这样越过顶部包含一个表情符号时,应该考虑我被讽刺的可能性。
G-Man说'Resstate Monica''Feb

10

尽管这里有几种有效的解决方案,但有时可能有用的另一种语法是在中运行命令<()。这将允许您在命令行上创建多个1的文件描述符对象。

当您执行比较长文本字符串之类的操作时,或者想要比较文件中未包含的某些内容时,此功能很有用。

例如,比较两个节点上的主机文件,而不必将主机文件复制到本地主机:

diff -Naur <(cat /etc/hosts) <(ssh -q otherhost 'cat /etc/hosts')

<重定向一个文件STDIN,并()创建一个子shell来运行括号之间的命令。是子外壳程序的STDOUT传递给正在运行的命令的STDIN。

与尝试使用多个此处文档或尝试将多个命令回显到最终命令的管道相比,为命令创建多个输入“文件”是一种更简单的方法。


<fileorpathname重定向标准输入,但<(subcmd)不重定向;它替换为一个名称,该名称在/如果由程序打开时可以从subcmd读取stdout。< <(subcmd)(需要空间)确实从该文件重定向stdin,就像subcmd |。您diff可以通过指定一个参数(但不能同时指定两个参数)从stdin 读取其输入之一-
dave_thompson_085 '17

这是不支持的流程替换,这与您声称已取消的部分不同(但并不像dave解释的那样)。
phk

1
我的差异在必须测试的Ubuntu 16.04和Solaris 11.2系统上的bash中工作正常。有可能它可能不适用于所有操作系统上的所有外壳。它实际上是在创建文件描述符,该文件描述符可用于读取子进程的输出,就像读取文件一样。由于diff需要两个文件参数,因此它能够通过创建的文件描述符读取两个子进程的输出,并进行比较。
肯尼迪

您可能希望在答案中加上cmd <(cmd2 ...)和之间的区别cmd < <(cmd2 ...)。前者允许使用派生数据(cmd2的输出)代替文件名。后者等效于cmd2 ... | cmd。必须编写命令以明确接受标准输入,而许多命令则不能。Shell脚本尤其如此。
DocSalvager

8

你可以用管子

echo "apple pear orange" | wc

8
管道与“从文件读取”不同。例如,您不能在管道中向后搜索,而可以在文件中。
rbialon '17

0

您可能想要使用类似的东西。以下是打开远程telnet会话,等待提示,发送一些数据,等待响应,休眠并退出的简单示例。

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.