Как я могу отправить символы в команду, как если бы они пришли из файла?

22

Как я могу отправить символы в команду, как если бы они пришли из файла?

Например я попробовал:

wc < "apple pear orange"
-bash: apple pear orange: No such file or directory
Тайлер Дурден
источник

Ответы:

32

В оболочках, которые поддерживают здесь строки , в том числе bash, zshи ksh93вы можете использовать

wc <<< "apple pear orange"
steeldriver
источник
@Kusalananda спасибо - я отредактировал вашу информацию в
steeldriver
18

Два других подхода (которые допускают многострочный ввод без дополнительных усилий):

  1. Используйте «здесь документ»:

    $ wc << EOF
    яблоко груша апельсин
    EOF
      1 3 18
    $

    EOFСтрока является разделителем. Вы можете использовать любую строку; EOFэто просто обычный выбор.

  2. Используйте tty в качестве ввода:

    $ туалет
    яблоко груша апельсин
    Ctrl+D
      1 3 18
    $

    Это имеет тот недостаток, что программа запускается и начинает читать ввод, как только вы набираете его имя. Это может сбивать с толку; например:

    $ grep v
    Быстрая коричневая лиса              (печатается) 
    перепрыгивает                       (печатается) 
    перепрыгивает                       (это вывод из grep!) 
    Ленивого пса.                   (напечатано)
    Ctrl + D
                                    (здесь нет выходных данных) 
    $
G-Man говорит: «Восстанови Монику»
источник
Для записи: <<<Форма также допускает многострочный ввод без лишних усилий, так как "строка -enclosed может содержать символы новой строки. Конечно, << EOFформу (оригинальный синтаксис here-doc) легче читать, если у вас есть многострочный ввод.
Alexis
Страница man говорит, что здесь синтаксис строки <<< word- конечно, в контексте оболочки, a wordможет быть строкой в ​​кавычках, содержащей пробелы и переводы строки! D'о! Это настолько очевидно, что само собой разумеется (и, на самом деле, я вообще не вижу этого упоминания на странице руководства). :-( Спасибо, что указал мне на это!
G-Man говорит: «Восстановите Монику»
Я бы не назвал это простым или очевидным, правда. A wordопределяется на странице руководства как «последовательность символов, рассматриваемая оболочкой как единое целое» (или «токен»), и вам необходимо знать, что строки в кавычках обрабатываются как «единичная единица» в соответствующем смысле (после обработка обратной косой черты, расширение переменных и т. д. «Но на самом деле в этом и заключается цель двойных кавычек в оболочке. (Одиночные кавычки также защищают от расширения.) Модель обработки оболочки очень хорошо продумана и совсем не проста.
alexis
@alexis: Когда я иду через вершину , как , что и включают в себя смайлик, следует рассмотреть возможность того, что я иронизирую.
G-Man говорит: «Восстановите Монику»
10

Хотя здесь есть несколько допустимых решений, другой синтаксис, который иногда может быть полезен, - запустить команду <(). Это позволит вам создать более 1 объекта дескриптора файла в командной строке.

Это может быть полезно, когда вы делаете что-то вроде сравнения длинных строк текста, или если вы хотите просмотреть какой-либо контент, которого нет в файле.

Например, сравнивая файлы hosts на двух узлах без необходимости копировать файл hosts на локальный хост:

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

<Перенаправляет файл STDIN и ()создать подоболочку для запуска команды между скобками. Это STDOUT из подоболочки, который передается в STDIN запускаемой команды.

Это более простой способ создать более 1 входного «файла» для команды, чем пытаться использовать несколько приведенных здесь документов или пытаться отобразить несколько команд в конвейере для последней команды.

Тим Кеннеди
источник
<fileorpathnameперенаправляет стандартный ввод, но <(subcmd)не делает; он заменяет имя, которое при открытии программой может прочитать стандартный вывод из subcmd. < <(subcmd)(требуется место) перенаправляет стандартный ввод из этого файла, почти как subcmd |. Вы diffмогли бы прочитать один из его входных данных из stdin, указав аргумент, -но не оба.
dave_thompson_085
Это подмена процесса, которая не поддерживается, в отличие от частей, которые, как вы утверждаете, сделаны (но это не так, как объяснил Дэйв).
PHK
1
Мой diff отлично работает в bash на Ubuntu 16.04 и системах Solaris 11.2, с которыми мне приходится тестировать. Возможно, он не будет работать для всех оболочек во всех операционных системах. Это фактически создание файловых дескрипторов, которые можно использовать для чтения выходных данных подпроцесса, как если бы он читал файл. Поскольку diff принимает два аргумента файла, он может прочитать выходные данные обоих подпроцессов через созданные файловые дескрипторы и сравнить их.
Тим Кеннеди
Вы можете добавить к своему ответу разницу между cmd <(cmd2 ...)и cmd < <(cmd2 ...). Первый позволяет использовать производные данные (вывод cmd2) вместо имени файла. Последнее эквивалентно cmd2 ... | cmd. Команды должны быть написаны так, чтобы явно принимать ввод stdin, а многие нет. Это особенно верно для сценариев оболочки.
DocSalvager
8

Вы можете использовать трубу

echo "apple pear orange" | wc
Slh47
источник
8
Труба не то же самое, что "чтение из файла". Например, вы не можете искать назад в трубе, тогда как вы можете в файле.
rbialon
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
Анонимный трус
источник