Znalazłem (use '[clojure.java.shell :only [sh]])
do wykonywania poleceń powłoki z clojure. Teraz, gdy (sh "ls" "-a")
wykonuje to zadanie, (sh "ls" "-a" "| grep" "Doc")
nie. Co to za sztuczka?Clojure: jak wykonywać polecenia powłoki za pomocą przewodów rurowych?
Odpowiedz
wykonuje polecenie (pierwszy argument przekazany do funkcji sh
) z określonymi argumentami (pozostałe parametry przekazano do sh
).
Po wykonaniu:
(sh "ls" "-a" "| grep" "Doc")
pytasz wykonać ls
z parametrami -a
, | grep
i Doc
.
Po wpisaniu ls -a | grep Doc
w terminalu następnie powłoka interpretuje go jako wykonujący ls
, podjęciem std się i przekazać go jako std do innego procesu (grep
), który powinien rozpocząć powłoki.
Można symulować działanie powłoki, uruchamiając ls
jako jeden proces, pobierając jego standardowe wyjście, a następnie wykonując grep
przekazując dane wyjściowe z ls
jako dane wejściowe.
Im prostsze rozwiązanie byłoby po prostu zapytać shell
proces do wykonania wszystkiego, jak gdyby był wpisany w terminalu:
(sh "bash" "-c" "ls -a | grep Doc")
Ważne jest, aby zdać -c
i ls ...
odsunięte tak bash dostaje je jako oddzielne parametry. Musisz również mieć całe polecenie, które chcesz wykonać jako jeden ciąg (ls -a | grep Doc
). W przeciwnym razie tylko pierwszy argument po -c
będzie traktowany jako polecenie. Na przykład nie będzie robić to, co chcesz:
(sh "bash" "-c" "ls -a" "|" "grep Doc")
To jest bardzo dobrze wyjaśnione odpowiedź, dziękuję! Teraz tylko dla czystej wiedzy, czy istnieje sposób, aby to zrobić, wysyłając w rzeczywistości wynik '(": out (sh "ls" "-a")) 'do innego' (sh "grep" "Doc") '? – shakedzy
Możesz użyć opcji ': in' opcji' sh', aby przekazać wartość ': out' z poprzedniego procesu, jednak używając go stracisz funkcję przesyłania strumieniowego danych z jednego procesu do innego - buforujesz wszystkie wyjście z jednego procesu i po jego zakończeniu przekazujesz całą jego zawartość do innego, a Shell używa potoków, w których dane są przesyłane strumieniowo z jednego procesu do drugiego bez potrzeby buforowania wszystkiego.Możesz użyć 'java.lang.Runtime.exec()' i 'java.lang.Process.getOutputStream', aby uzyskać dane wyjściowe z pierwszego procesu i przekazać je do następnego, ale Clojure' sh' nie obsługuje tego. –
Możesz również rzucić okiem na https: // github .com/Raynes/koncha. Obsługuje potoki: https://github.com/Raynes/conch#piping –