Przekaż tekst do programu oczekującego pliku


30

Powiązane z pytaniem, które zadałem na temat przepełnienia stosu: przekazanie wielu wierszy kodu do pliku wsadmin.sh? .

Mam jako ciąg kilka wierszy danych wejściowych, które muszę wprowadzić do polecenia. Komenda akceptuje jednak tylko plik pełen danych wejściowych.

Czy jest jakiś sposób, aby zapisać wiersze w tymczasowym pliku lub potoku, który nigdy nie jest zapisywany na dysku, a następnie podawany bezpośrednio do programu?

Jak mogę zdobyć rurę, wprowadzić do niej dane wejściowe, przekazać tę komendę do polecenia, a następnie pozbyć się rury?


2
Czy możesz dodać przykład polecenia, którego używasz, i jak ma zostać wywołane?
— Przełom

2
Czy to oznacza, że ​​program nie akceptuje standardowego wejścia?
— Léo Lam,

Zgadzam się z obu komentatorami powyżej. Niemożliwe jest sugerowanie czegokolwiek, co mogłoby działać bez znajomości specyfikacji programu.
— Larssend,

Odpowiedzi:


27

Innym rozwiązaniem jest użycie procesu podstawiania w Bash. Jeśli twój system nazwał rury, możesz użyć tej funkcji.

Używa się go w następujący sposób:

program_expecting_a_file <(list)

gdzie listjest sekwencją poleceń powłoki (właściwie potoków; pełne szczegóły są tutaj ). listzostanie wykonany, a jego wyjście zostanie podłączone do potoku. Nazwa potoku jest następnie przekazywana do Twojego programu.

UWAGA: spacje nie są dozwolone między <a (.

(Inne podstawienie >(list)działa również tak, jak można się spodziewać).

W twoim konkretnym przypadku możesz użyć

program_expecting_a_file <(echo "$your_strings")

chociaż może się okazać, że rozwiązanie @ meuh jest bardziej eleganckie.

Aktualizacja: wiele przykładów użycia można znaleźć w przewodniku Advanced Bash Scripting Guide .


Pozostałe dwie nie działały nawet w najbardziej trywialnych przypadkach. Twój zdaje testy, które do tej pory na niego rzuciłem. Na razie głosowałem za tobą. Wrócę i oznaczę to jako zaakceptowane, jeśli zrobi wszystko, czego potrzebuję.
— ArtOfWarfare

Twoje działa idealnie. Jeśli chcesz, możesz dodać to do powiązanego pytania na StackOverflow, a ja też mogę je zaakceptować. stackoverflow.com/questions/31374202/…
— ArtOfWarfare

Cześć @ ArtOfWarfare, cieszę się, że mogłem pomóc. Jest tam już komentarz dotyczący tego samego proponowanego rozwiązania, więc nie byłoby dla mnie właściwe zamieszczanie tam odpowiedzi.
— Edward

Opublikowałeś swoje rozwiązanie, zanim on to zrobił. W każdym razie poprosiłem go, aby zmienił swój komentarz na odpowiedź, abym mógł ją zaakceptować. Jeśli żadne z was nie opublikuje odpowiedzi w ciągu ~ 24 godzin na to pytanie, po prostu opublikuję odpowiedź, aby ją zaakceptować (nie lubię pozostawiać pytań bez odpowiedzi, gdy tylko znajdę odpowiedź. po prostu złe maniery dla przyszłych czytelników / potencjalnych odpowiedzi na pytanie.)
— ArtOfWarfare

Cześć @ ArtOfWarfare, jestem absolutnie w porządku z tym, co proponujesz!
— Edward

15

Możesz użyć bash tutaj-doc . Na przykład,

$ cat -n <<<'a
> b'
 1  a
 2  b

Jeśli masz coś w zmiennej bash, możesz ją również interpolować: np <<<"path is $PATH".


Jeśli twoje polecenie nalega na nazwę pliku, możesz go podać /dev/stdin. Na przykład:

$ sed -f /dev/stdin <<<'s/a/b/'

produkuje wyjście: s/b/b/.


Pytanie, czy polecenie przyjmuje dane wejściowe stdin, nie jest jasne , a jeśli nie, to nie zadziała. Mam nadzieję, że PO wyjaśni.
— David Z

1
:( - Wydawało się to bardzo obiecujące, ale kiedy spróbowałem, dostałem komunikat o błędzie"-f" option must be followed by a file name.
— ArtOfWarfare

Dokument tutaj jest dla standardowego. Jeśli twoje polecenie absolutnie potrzebuje -fnazwy pliku, podaj nazwę pliku /dev/stdin. Zobacz moją edycję.
— Meuh

Myślę, że po edycji jest to absolutnie realna opcja!
— Edward

1
+1 za /dev/stdinsugestię. Program, który próbuję wywołać, przyjmuje tylko nazwę pliku, więc połączyłem się /dev/stdinz heredoc.
— Huw Walters

7

W zależności od tego, co jest w scenariuszu, to może być w stanie użyć specjalnego pliku - (minus), który stoi na stdin

$ mycmd -
Line 1
Line 2
^D

Inną metodą, która może Ci pomóc, jest otwarcie pliku, /dev/fd/0który znowu oznacza stdin .

Trzecią opcją może być utworzenie FIFO (First In First Out). To jest jak plik, ale ma dwa końce - piszesz na jednym końcu, a czytasz na drugim.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo

3
Warto zauważyć, że program musi być napisany, aby interpretować w -ten sposób - nie jest to cecha powłoki ani systemu operacyjnego. Oczywiście, o ile wiem, większość standardowych narzędzi Linuksa stosuje się do tej konwencji.
— David Z

1
Nie. To nie działa dla programu. Istnieje tryb interaktywny, ale chcę przekazać polecenia do wykonania tego programu z innego programu i nie chcę dostać się do króliczej nory expect.
— ArtOfWarfare

@ArtOfWarfare Właśnie dodałem trzecią opcję, która może działać.
— Majenko,

Niezła odpowiedź! Druga i trzecia opcja są w zasadzie podobne do <()rozwiązania, ale bardziej wyraźne - co może być bardzo przydatne!
— Edward

4

Istnieje inna opcja podobna do mycmd -rozwiązania, ale nawet w przypadku programów, które nie obsługują -konkretnie:

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin wydaje się być związany z systemem operacyjnym i działa dla mnie na Debian GNU / Linux, ale nie jestem pewien, gdzie jeszcze to zadziała.


1
Wygląda na to, że może działać, ale co to jest ^D?
— ArtOfWarfare

^Djest powszechną notacją do naciskania Ctrl-D. ^ D ma tutaj semantykę „końca strumienia wejściowego”. Prawdopodobnie jest częściej widoczny w ^Club ^Zktóry oznacza naciśnięcie Ctrl-C odpowiednio do naciśnięcia Ctrl-Z.
— Axel Beckert

1
Wydaje się, że to działa, ale jak mam programowo włożyć rzeczy, /dev/stdina następnie je zamknąć?
— ArtOfWarfare

1
Wystarczy potokować coś do tego polecenia i powinno działać, tj cat content | mycmd /dev/stdin. Wyobraź sobie inne polecenia niż cattutaj.
— Axel Beckert
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.