Chcę raz uruchomić polecenie Java dla każdego dopasowania ls | grep pattern -
. W tym przypadku myślę, że mógłbym to zrobić, find pattern -exec java MyProg '{}' \;
ale ciekawi mnie ogólny przypadek - czy można łatwo powiedzieć „uruchom polecenie raz dla każdego wiersza standardowego wejścia”? (W rybach lub bash.)
162
printf "foo bar\nbaz bat" | xargs echo whee
ustąpiwhee foo bar baz bat
. Może dodać opcje-L
lub-n
?Przyjęte rozwiązanie ma rację, ale kluczowe jest, aby przejść
xargs
do-n1
przełącznika, co oznacza „Wykonaj polecenie po każdym wierszu wyjścia”Lub, dla jednego pliku wejściowego, możesz
cat
całkowicie uniknąć potoku i po prostu przejść z:źródło
xargs
do nie działać, jeślistdin
jest pusta:--no-run-if-empty
-r
: Jeżeli standardowe wejście nie zawiera żadnych nonblanks, nie działają komendy. Zwykle polecenie jest uruchamiane raz, nawet jeśli nie ma danych wejściowych. Ta opcja jest rozszerzeniem GNU.command
?W Bash lub innej powłoce w stylu Bourne'a (jesion, ksh, zsh,…):
read -r
czyta pojedynczy wiersz ze standardowego wejścia (read
bez-r
interpretacji ukośników odwrotnych, nie chcesz tego). W ten sposób możesz wykonać jedną z następujących czynności:źródło
tail -f syslog | grep -e something -e somethingelse| while read line; do echo $line; done
, nie działało. Działało z plikiem podłączonym dowhile
pętli, działało z samymtail -f
, działało z tylkogrep
, ale nie z obiema rurami. Dającgrep
się--line-buffered
opcję wykonane pracowaćcommand | while read -r line; do echo "$line" | command ; done
Zgadzam się z Keith, xargs jest najbardziej ogólnym narzędziem do tego zadania.
Zwykle stosuję podejście 3-etapowe.
Istnieją mniejsze i szybsze sposoby, ale te sposoby prawie zawsze działają.
Prosty przykład:
2 pierwsze linie wybierają niektóre pliki do pracy, a następnie awk przygotowuje ładny ciąg z poleceniem do wykonania i pewnymi argumentami, a $ 1 to pierwsza kolumna wejściowa z potoku. I wreszcie upewniam się, że xargs wysyła ten ciąg do bash, który po prostu go wykonuje.
To trochę przesada, ale ten przepis pomógł mi w wielu miejscach, ponieważ jest bardzo elastyczny.
źródło
xargs -0
używa bajtu zerowego jako separatora rekordów, więc twoja instrukcja drukowania awk powinna byćprintf("MyJavaProg --args \"%s\"\0",$1)
awk
, możesz zrobić to dopasowując wzór i pominąćgrep
np.ls | awk '/xls/ {print...
GNU Parallel jest przeznaczony do tego rodzaju zadań. Najprostsze użycie to:
Obejrzyj film wprowadzający, aby dowiedzieć się więcej: http://www.youtube.com/watch?v=OpaiGYxkSuQ
źródło
cat
tu potrzeby , ponieważgrep
można bezpośrednio odczytać plik< stuff grep pattern
alegrep pattern stuff
nie wymaga przekierowania ani kota. Mimo to nie zmienia to w istotny sposób twojego argumentu, a jeśli uważasz, że łatwiej jest zawsze używać rzeczy w rurze, która zaczyna się odcat
, a potem moc dla ciebiePonadto,
while read
włóż skorupkę ryby (zakładam, że chcesz skorupkę ryby, biorąc pod uwagę, że użyłeś etykiety rybnej ).Kilka punktów do odnotowania.
read
nie bierze-r
argumentów i nie interpretuje ukośników odwrotnych, aby ułatwić najczęstsze przypadki użycia.$line
, ponieważ w przeciwieństwie do bash, ryby nie oddzielają zmiennych spacjami.command
sam w sobie jest błędem składniowym (aby złapać takie użycie argumentów zastępczych). Zamień go na prawdziwe polecenie.źródło
while
trzeba go łączyć zdo
&done
zamiastend
?Jeśli chcesz kontrolować, gdzie dokładnie argument wejściowy jest wstawiany do wiersza poleceń lub jeśli chcesz go powtórzyć kilka razy, musisz użyć
PRZYKŁAD 1xargs -I{}
.Utwórz pustą strukturę folderów,
PRZYKŁAD 2another_folder
która odzwierciedla podfoldery w bieżącym katalogu:Zastosuj operację na liście plików pochodzących ze standardowego wejścia, w tym przypadku wykonaj kopię każdego
.html
pliku, dołączając.bak
rozszerzenie:Ze strony podręcznika
xargs
dla MacOS / BSD :Linux
xargs
strona man :źródło
Kiedy mam do czynienia z potencjalnie niezaangażowanymi danymi wejściowymi, lubię widzieć, jak całe zadanie „pisze się” wiersz po wierszu do kontroli wizualnej, zanim go uruchomię (szczególnie, gdy jest to coś destrukcyjnego, jak czyszczenie skrzynek pocztowych ludzi).
Więc to, co robię, to wygenerowanie listy parametrów (tj. Nazw użytkowników), przesłanie jej do pliku w sposób jeden rekord na linię, jak poniżej:
Następnie otwieram listę
vim
i zmieniam ją za pomocą wyszukiwania i zamieniam wyrażenia, aż otrzymam listę pełnych poleceń, które należy wykonać, w następujący sposób:W ten sposób, jeśli wyrażenie regularne jest niekompletne, zobaczysz, w jakim poleceniu wystąpią potencjalne problemy (tj.
/bin/rm -fr johnnyo connor
). W ten sposób możesz cofnąć wyrażenie regularne i spróbować ponownie, używając bardziej niezawodnej wersji. Zmiana nazwy jest znana z tego powodu, ponieważ ciężko jest zająć się wszystkimi przypadkowymi przypadkami, takimi jak Van Gogh, O'Connors, St. Clair, Smith-Wesson.Mając
set hlsearch
jest przydatna w ten sposóbvim
, jak to podkreślają wszystkie mecze, więc można łatwo dostrzec, jeśli nie pasuje, lub mecze w niezamierzony sposób.Gdy wyrażenie regularne jest idealne i obejmuje wszystkie przypadki, w których można przetestować / wymyślić, zwykle przekształcam je w wyrażenie sed, aby można je było w pełni zautomatyzować do kolejnego uruchomienia.
W przypadkach, w których liczba wierszy danych wejściowych uniemożliwia sprawdzenie wizualne, zdecydowanie polecam powtórzenie polecenia na ekranie (lub jeszcze lepiej w dzienniku) przed jego wykonaniem, więc jeśli wystąpi błąd, dokładnie wiesz, które polecenie spowodowało zawieść. Następnie możesz wrócić do pierwotnego wyrażenia regularnego i dostosować go jeszcze raz.
źródło
Jeśli program ignoruje potok, ale akceptuje pliki jako argumenty, możesz po prostu wskazać specjalny plik
/dev/stdin
.Nie znam java, ale oto przykład, jak zrobiłbyś to dla bash:
$ Jest niezbędny, aby bash mógł zostać przetłumaczony
\n
na nowe linie. Nie jestem pewien dlaczego.źródło
Wolę to - pozwalając na wieloliniowe polecenia i czysty kod
ref https://stackoverflow.com/a/3891678/248616
źródło