2014-04-17 15 views
11

tutaj jest mój problem w krótkimxargs podzielone na nie nowych linii obowiązuje

$ echo 'for i in [email protected]; do echo arg: $i; done; echo DONE' > /tmp/test.sh 
$ echo "ac\nbc\ncc\n" | xargs bash /tmp/test.sh 
arg: ac 
arg: bc 
arg: cc 
DONE 

która jest, co się spodziewać, ale

$ echo "ac s\nbc s\ncc s\n" | xargs -d \n bash /tmp/test.sh 
arg: ac 
arg: s 
arg: bc 
arg: s 
arg: cc 
arg: s 
DONE 

nie powinno być wyjście?

Jak uzyskać drugie wyjście z xargs?

Odpowiedz

11

Spróbuj:

printf %b 'ac s\nbc s\ncc s\n' | xargs -d '\n' bash /tmp/test.sh 

Ty zaniedbane zacytować \n przekazany do -d, co oznacza, że ​​tylko n zamiast \n został przekazany do xargs jako ogranicznik - skorupa "zjadł" THE \ (gdy powłoka analizuje niecytowany ciąg znaków, \ działa jako znak escape, a jeśli zwykła postać podąża za \ - n w tym przypadku - używany jest tylko ten zwykły znak).

Zwróć także uwagę na zalecenie @glenn jackman, aby dwukrotnie zacytować [email protected] w skrypcie (lub całkowicie pomiń część in "[email protected]").

Również: xargs -d to rozszerzenie GNU, które na przykład nie działa w FreeBSD/macOS. Aby to działało, zobacz rozwiązanie oparte na @glenn jackman's xargs -0.


Zauważ, że używam printf zamiast echo aby upewnić się, że \n przypadki w ciągu są interpretowane jako nowymi liniami w wszystkie Bourne'a jak muszle:
W bash i ksh[1] , echo domyślnie NIE interpretuje \-sekwencji ucieczki (musisz użyć -e, aby to osiągnąć) - w przeciwieństwie do zsh i ściśle zgodnych z POSIX-ami powłok, takich jak dash.
Dlatego też bardziej przenośny wybór to printf.

[1] zgodnie z podręcznikiem ksh jest echowbudowane wykazuje takie samo zachowanie jak zewnętrznego echonarzędzie platformy przyjmującej; chociaż może się to różnić w zależności od platformy, implementacje Linuksa i BSD/OSX domyślnie interpretują sekwencje specjalne.

5

Twój skrypt musi użyć "[email protected]" nie [email protected]

Zobacz http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters


widzę w instrukcji xargs na moim komputerze:

xargs czyta elementy ze standardowego wejścia , wytyczony przez puste miejsca [...] lub znaki nowej linii

(Kopalnia nacisk)

Zatem:

$ echo $'ac s\nbc s\ncc s\n' | xargs bash /tmp/test.sh 
arg: ac 
arg: s 
arg: bc 
arg: s 
arg: cc 
arg: s 
DONE 

$ printf "%s\0" "ac s" "bc s" "cc s" | xargs -0 bash /tmp/test.sh 
arg: ac s 
arg: bc s 
arg: cc s 
DONE 

z byłym, można dostać równowartość

bash /tmp/test.sh ac s bc s cc s 

kontra stosując zerową-separator

bash /tmp/test.sh "ac s" "bc s" "cc s" 

Musisz mieć jasność co do tego, czym jest ogranicznik z xargs, gdy dane zawierają spacje.

$ printf "%s\n" "ac s" "bc s" "cc s" | xargs -d $'\n' bash /tmp/test.sh 
arg: ac s 
arg: bc s 
arg: cc s 
DONE 

$ echo $'ac s\nbc s\ncc s\n' | xargs -d $'\n' bash /tmp/test.sh 
arg: ac s 
arg: bc s 
arg: cc s 
arg: 
DONE 

Uwaga dodatkowa arg w tym ostatnim przypadku, echo już dodaje nowej linii, więc nie trzeba dodatkowo jeden jeśli używasz echo -n

+0

Dobra rada, choć prawdziwy problem leży nie cytując '\ n' przekazano do' -d'. – mklement0

+0

To osobny numer, ale dzięki za wskazanie. –

+1

Masz całkowitą rację: _obowiązuje wiele problemów, aby rozwiązać problem (i każdy z nich w izolacji lub w połączeniu wytwarza symptomy). Twoje rozwiązanie 'printf' -' \ 0' -'xargs -0' jest dobrą alternatywą, ponieważ jest bardziej przenośne (będzie działać również na OSX, na przykład, gdy' xargs -d' nie jest dostępny). – mklement0