Jak mogę wysłać znaki do polecenia tak, jakby pochodziły z pliku?

22

Jak mogę wysłać znaki do polecenia tak, jakby pochodziły z pliku?

Na przykład próbowałem:

wc < "apple pear orange"
-bash: apple pear orange: No such file or directory
Tyler Durden
źródło

Odpowiedzi:

32

W muszli, które obsługują tutaj ciągi , w tym bash, zshi ksh93można użyć

wc <<< "apple pear orange"
steeldriver
źródło
@Kusalananda dzięki - edytowałem twoje informacje w
steeldriver
18

Dwa inne podejścia (które umożliwiają wprowadzanie wielu wierszy bez dodatkowego wysiłku):

  1. Użyj „tutaj dokumentu”:

    $ wc << EOF
    jabłko-gruszka pomarańczowa
    EOF
      1 3 18
    $

    EOFCiąg jest separator. Możesz użyć dowolnego ciągu; EOFjest tylko konwencjonalnym wyborem.

  2. Użyj tty jako danych wejściowych:

    $ wc
    jabłko-gruszka pomarańczowa
    Ctrl+D
      1 3 18
    $

    Ma to tę wadę, że program zaczyna działać i zaczyna czytać dane wejściowe, gdy tylko wpiszesz jego nazwę. Może to być niepokojące; na przykład:

    $ grep v
    Szybki brązowy lis              (na maszynie) 
    przeskakuje                       (na maszynie) 
    przeskakuje                       (To jest wyjście z grep!) 
    Leniwy pies.                   (wpisany)
    Ctrl + D
                                    (tutaj brak wyników) 
    $
G-Man mówi „Przywróć Monikę”
źródło
Dla przypomnienia : <<<Formularz umożliwia także wprowadzanie wielu wierszy bez dodatkowego wysiłku, ponieważ "zamknięty łańcuch może zawierać znaki nowej linii. Oczywiście << EOFformularz (oryginalna składnia tutaj-doc) jest łatwiejszy do odczytania, jeśli masz wejście wieloliniowe.
Alexis
Strona man mówi, że tutaj składnia ciągów znaków <<< word- oczywiście w kontekście powłoki, a wordmoże być ciągiem cytowanym, zawierającym spacje i znaki nowej linii! Nie! Jest to tak oczywiste, że jest oczywiste (i w rzeczywistości nie widzę o tym w ogóle na stronie podręcznika). :-( Dziękujemy za zwrócenie mi uwagi!
G-Man mówi „Przywróć Monikę”
Naprawdę nie nazwałbym tego prostym ani oczywistym. A wordjest zdefiniowane na stronie podręcznika jako „Sekwencja znaków uważanych przez powłokę za pojedynczą jednostkę” (aka „token”), i musisz wiedzieć, że cytowane ciągi znaków są traktowane jako „pojedyncza jednostka” w odpowiednim znaczeniu (po przetwarzanie odwrotnego ukośnika, zmienna ekspansja itp. „Ale to jest właśnie ten cel podwójnego cytowania w powłoce. (Pojedyncze cudzysłowy chronią także przed ekspansją). Model przetwarzania powłoki jest bardzo dobrze przemyślany i wcale nie prosty.
Alexis
@alexis: Kiedy przechodzę w ten sposób do góry i dołączam emotikon, należy wziąć pod uwagę możliwość, że jestem ironiczny.
G-Man mówi „Przywróć Monikę”
10

Chociaż istnieje tutaj kilka poprawnych rozwiązań, inną składnią, która może być czasem przydatna, jest uruchomienie polecenia <(). Umożliwiłoby to utworzenie więcej niż 1 obiektu deskryptora pliku w wierszu polecenia.

Może to być przydatne, gdy robisz coś takiego jak porównywanie długich ciągów tekstu lub jeśli chcesz różnicować zawartość, której nie ma w pliku.

Na przykład porównanie plików hosts na dwóch węzłach bez konieczności kopiowania pliku hosts na localhost:

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

<Przekierowuje plik do standardowego wejścia i ()tworzyć podpowłoce uruchomić polecenie między nawiasach. Jest to STDOUT z podpowłoki, która jest przekazywana do STDIN uruchamianego polecenia.

To łatwiejszy sposób na utworzenie więcej niż 1 wejściowego „pliku” do polecenia niż próba użycia wielu tutaj dokumentów lub próba powtórzenia wielu poleceń w potoku do ostatecznego polecenia.

Tim Kennedy
źródło
<fileorpathnameprzekierowuje standardowe wejście, ale <(subcmd)nie; zastępuje nazwę, która gdy / jeśli zostanie otwarta przez program, może odczytać standardowe wyjście z subcmd. < <(subcmd)(wymagane miejsce) przekierowuje standardowe wejście z tego pliku, prawie jaksubcmd | . Możesz diffodczytać jeden z jego danych wejściowych ze standardowego wejścia, podając argument, -ale nie oba.
dave_thompson_085
Jest to podstawianie procesów, które nie jest obsługiwane, w przeciwieństwie do części, które, jak twierdzisz, zostały wykonane (ale nie jest tak, jak wyjaśnił Dave).
phk
1
Mój diff działa dobrze w bash na systemach Ubuntu 16.04 i Solaris 11.2, z którymi muszę testować. Możliwe, że może nie działać dla wszystkich powłok we wszystkich systemach operacyjnych. W rzeczywistości tworzy deskryptory plików, których można użyć do odczytania danych wyjściowych z podprocesu tak, jakby czytał plik. Ponieważ diff pobiera dwa argumenty pliku, jest w stanie odczytać dane wyjściowe obu podprocesów poprzez utworzone deskryptory plików i porównać je.
Tim Kennedy,
Możesz dodać do swojej odpowiedzi różnicę między cmd <(cmd2 ...) i cmd < <(cmd2 ...). Pierwszy pozwala na wykorzystanie danych pochodnych (danych wyjściowych cmd2) zamiast nazwy pliku. Ten ostatni jest równoważny cmd2 ... | cmd. Polecenia muszą być napisane, aby jawnie akceptować wejście standardowego wejścia, a wiele z nich nie. Dotyczy to zwłaszcza skryptów powłoki.
DocSalvager
8

możesz użyć fajki

echo "apple pear orange" | wc
Slh47
źródło
8
Potok nie jest tym samym, co „odczyt z pliku”. Na przykład nie możesz wyszukiwać wstecz w potoku, podczas gdy możesz w pliku.
rbialon
0

Możesz użyć czegoś podobnego, aby się spodziewać. Poniżej znajduje się prosty przykład otwarcia zdalnej sesji telnet, oczekiwania na monit, wysłania danych, oczekiwania na odpowiedź, uśpienia i wyjścia.

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
Anonimowy Tchórz
źródło