Mam program UNIX czarnej skrzynki używany w powłoce Bash, która odczytuje kolumny danych ze standardowego wejścia, przetwarza je (stosując efekt wygładzania), a następnie wysyła do standardowego wyjścia. Używam go przez potoki UNIX, jak
generate | smooth | plot
Aby uzyskać bardziej wygładzanie, mogę powtórzyć wygładzanie, aby można je było wywołać z wiersza poleceń Bash jako
generate | smooth | smooth | plot
lub nawet
generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot
To staje się coraz trudniejsze. Chciałbym, aby otoki Bash były w stanie wpakować smooth
i przekazać dane wyjściowe z powrotem do nowej instancji smooth
dowolnej liczby razy, coś w rodzaju
generate | newsmooth 5 | plot
zamiast
generate | smooth | smooth | smooth | smooth | smooth | plot
Moją pierwszą próbą był skrypt Bash, który wygenerował pliki tymczasowe w bieżącym katalogu i usunął je, ale okazał się brzydki, gdy nie było mnie w katalogu z dostępem do zapisu, a także pozostawił pliki śmieci po przerwaniu.
Brak argumentów do smooth
programu.
Czy istnieje bardziej elegancki sposób na „zawinięcie” takiego programu w celu sparametryzowania liczby połączeń?
źródło
Odpowiedzi:
Możesz zawinąć go w funkcję rekurencyjną:
Użyłbyś tego jako
co byłoby równoważne z
źródło
Jeśli możesz sobie pozwolić na wpisanie tylu przecinków, ile
smooth
chcesz, możesz skorzystać z oddzielonego przecinkami rozszerzenia nawiasów.TL; DR
Cały wiersz polecenia dla przykładowego przypadku to:
Uwaga:
smooth |
|
wcześniej,plot
ponieważ jest to uwzględnione w ostatnimsmooth |
ciągu wyprodukowanym przez Brace Expansionsmooth
, pod warunkiem, że umieścisz je poprawnie w cytowanej części stałej, która poprzedza otwarty nawias klamrowy; w każdym razie pamiętaj, że będziesz je przekazywał we wszystkich powtórzeniach poleceniaJak to działa
Rozwinięcie nawiasu rozdzielanego przecinkami umożliwia dynamiczne tworzenie ciągów, z których każdy składa się z określonej części stałej i określonych części zmiennych. Wytwarza tyle łańcuchów, ile jest wskazanych części zmiennych, takich jak
a{b,c,d}
produkujeab ac ad
.Mała sztuczka polega na tym, że jeśli raczej utworzysz listę pustych części zmiennych, tj. Z tylko przecinkami w nawiasach klamrowych, rozszerzenie nawiasów spowoduje tylko utworzenie kopii części stałej. Na przykład:
będzie produkować:
Zauważ, że 4 przecinki dają 5
smooth
ciągów. Właśnie tak działa ten Brace Expansion: tworzy ciągi znaków tyle przecinków plus jeden.Oczywiście w twoim przypadku potrzebujesz również
|
każdego oddzielającegosmooth
, więc po prostu dodaj go do części stałej, ale pamiętaj o prawidłowym cytowaniu, aby powłoka nie interpretowała go od razu. To jest:będzie produkować:
Zadbaj o to, aby zawsze umieszczać nieruchomą część bezpośrednio przylegającą do otwartej klamry, tzn. Nie odstępować między nią
'
a{
.(Zauważ również, że aby utworzyć część stałą, możesz również użyć podwójnych cudzysłowów zamiast pojedynczych cudzysłowów, jeśli chcesz rozwinąć zmienne powłoki w stałej części. Wystarczy zadbać o dodatkowe znaki ucieczki, które są wymagane, gdy pojawią się znaki specjalne niektórych powłok wewnątrz ciągu podwójnego cudzysłowu).
W tym momencie musisz
eval
zastosować ten ciąg, aby powłoka ostatecznie zinterpretowała go jako polecenie potokowe, jakie powinno być.Tak więc, podsumowując wszystko, cały wiersz polecenia dla twojego przykładowego przypadku wyglądałby następująco:
źródło
eval
gdy ktoś dostarcza niezaufane, niezanieczyszczone ciągi do oceny, to znaczy, gdy jest używany ze zmiennymi, które mogą zawierać „nieznane” treści, takie jak przypadek, który podłączyłeś. Z drugiej strony,eval
może być również bardzo przydatny do szybkiego „hydraulicznego” wykonywania poleceń, zwłaszcza gdy jest używany w wierszu poleceń, tak jak wydaje się w omawianym przypadku, gdzieeval
dane wejściowe byłyby tylko literalnym ciągiem znaków wpisanym ręcznie przez użytkownika w osobaeval str
coś pretensjonalnego i głupiego. /dev/stdin <<<str
. Nie tylko wywrze to wrażenie na głupcach, ale również powstrzyma @CharlesDuffy od twoich pleców ;-)