Як я можу надсилати символи команді так, ніби вони прийшли з файлу?


22

Як я можу надсилати символи команді так, ніби вони прийшли з файлу?

Наприклад, я спробував:

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

Відповіді:


32

У оболонках, які підтримують тут рядки , включаючи bash, zshі ksh93ви можете використовувати

wc <<< "apple pear orange"

@Kusalananda дякую - я відредагував вашу інформацію в
steeldriver

18

Ще два підходи (які дозволяють вводити багато рядків без зайвих зусиль):

  1. Використовуйте "тут документ":

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

    EOFРядок є роздільником. Ви можете використовувати будь-який рядок; EOF- це лише звичайний вибір.

  2. Використовуйте tty як вхід:

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

    Це має недолік, що програма починає працювати, і починає читати вхід, як тільки ви вводите його ім'я. Це може бути неприємно; наприклад:

    $ grep v
    Швидка бура лисиця              (набрана) 
    перестрибує                       (набрана), 
    перестрибує                       (Це виводиться з греп!) 
    Ледачої собаки.                   (набрано)
    Ctrl + D
                                    (тут немає виводу) 
    $

Для запису: <<<Форма також дозволяє вводити багато рядків без зайвих зусиль, оскільки "-закрита рядок може містити нові рядки. Звичайно, << EOFформа (оригінальний синтаксис тут-doc) легше читати, якщо у вас є багаторядковий ввід.
alexis

На сторінці man йдеться про те, що тут синтаксис рядків <<< word- це, звичайно, в контексті оболонки, а wordможе бути рядком, що цитується, що містить пробіли та нові рядки! D'oh! Це настільки очевидно, що це само собою зрозуміло (і насправді я взагалі не бачу його згадки на сторінці людини). :-( Дякую, що мені це вказали!
G-Man каже: "Відновіть Моніку"

Я б не назвав це простим чи очевидним, насправді. A wordвизначається на сторінці сторінки як "Послідовність символів, що розглядаються як одиночна одиниця оболонкою" (він же "маркер"), і вам потрібно знати, що цитовані рядки трактуються як "одна одиниця" у відповідному сенсі (після обробка зворотної косої риси, змінне розширення і т. д. "Але справді в цьому полягає вся мета подвійного котирування в оболонці. (Одиночні лапки також захищають від розширення.) Модель обробки оболонки дуже добре продумана, і нічого, крім простого.
alexis

@alexis: Коли я так переходжу над вершиною і включаю смайлик, варто розглянути можливість того, що я іронізую.
G-Man каже: "Відновіть Моніку"

10

Хоча тут є кілька дійсних рішень, ще один синтаксис, який може бути часом корисним, - це запустити команду в <(). Це дозволить вам створити більше 1 об’єкта файлового дескриптора в командному рядку.

Це може бути корисно, коли ви робите щось на зразок порівняння довгих рядків тексту або якщо ви хочете розмежувати деякий вміст, який відсутній у файлі.

Наприклад, порівняння файлів хостів на двох вузлах без необхідності копіювання файлу хостів у localhost:

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

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

Це простіший спосіб створити більше 1 вхідного "файлу" для команди, ніж намагатися використовувати декілька тут документів або намагатися повторити кілька команд у конвеєр до остаточної команди.


<fileorpathnameперенаправляє stdin, але <(subcmd)не робить; він підміняє ім'я, яке при відкритті програмою може читати stdout з subcmd. < <(subcmd)(потрібний простір) робить перенаправлення stdin з цього файлу, майже як subcmd |. Ви diffможете прочитати один із вхідних даних із stdin, вказавши аргумент, -але не те й інше.
dave_thompson_085

Це підміна процесу, яка не підтримується, на відміну від частин, на які ви стверджуєте, що вона завершена (але це не так, як пояснив Дейв).
phk

1
Моя розробка відмінно справляється з системою Ubuntu 16.04 та системами Solaris 11.2, з якою я маю тестувати. Можливо, це може не працювати для всіх оболонок у всіх операційних системах. Це фактично створення дескрипторів файлів, які можна використовувати для зчитування результатів з підпроцесу так, ніби вони читають файл. Оскільки diff займає два файлові аргументи, він може прочитати вихід обох підпроцесів через створені дескриптори файлів та порівняти їх.
Тім Кеннеді

Ви можете додати у відповідь різницю між cmd <(cmd2 ...)та cmd < <(cmd2 ...). Перший дозволяє отримати отримані дані (вихід cmd2) замість імені файлу. Останній еквівалентний cmd2 ... | cmd. Команди повинні бути написані, щоб явно прийняти введення stdin, і багато з них - ні. Особливо це стосується скриптів оболонок.
DocSalvager

8

можна використовувати трубу

echo "apple pear orange" | wc

8
Труба ist не є такою ж, як "читання з файлу". Наприклад, ви не можете шукати назад у трубі, тоді як у файлі.
rbialon

0

Можливо, ви хочете використовувати щось подібне для очікування. Далі наводиться простий приклад відкриття сеансу віддаленого телнету, очікування підказки, надсилання деяких даних, очікування відповіді, сну та виходу.

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.