2014-04-17 4 views
11

hier ist mein Problem in der kurzenxargs bei Zeilenumbrüchen geteilt keine Leerzeichen

$ 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 

Was ist das, was ich erwarten würde, aber

$ 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 

Sollte nicht der Ausgang sein?

arg: ac s 
arg: bc s 
arg: cc s 
DONE 

Wie bekomme ich die 2. Ausgabe mit Xargs?

Antwort

11

Versuchen:

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

Sie vernachlässigt die \n--d weitergegeben zu zitieren, was bedeutet, dass nur n anstatt \n-xargs als Trennzeichen übergeben wurde - die Schale „aß“ die \ (wenn Die Shell analysiert eine nicht angeführte Zeichenkette, \ fungiert als Escape-Zeichen, wenn in diesem Fall ein normales Zeichen dem \ - n folgt - wird nur dieses gewöhnliche Zeichen verwendet.

Beachten Sie auch @ glenn Jackman's Tipp, die [email protected] innerhalb des Skripts double-quote (oder lassen Sie die in "[email protected]" Teil insgesamt).

Auch: xargs -d ist eine GNU-Erweiterung, die zum Beispiel nicht auf FreeBSD/macOS funktioniert. Um es dort funktionieren zu lassen, sehen Sie sich @ glenn jackmans xargs -0 -basierte Lösung an.


Bitte beachte, dass ich printf bin mit eher als echo, um sicherzustellen, dass die \n Instanzen in der Zeichenfolge werden als neue Zeilen interpretieren in alle Bourne-wie Muscheln:
In bash und ksh[1]echo standardmäßig \ -basierte Escape-Sequenzen nicht interpretieren (Sie müssen -e verwenden, um dies zu erreichen) - im Gegensatz zu zsh und streng POSIX-konforme Shells wie dash.
Daher ist printf die tragbare Wahl.

[1] Laut Handbuch, ksh ‚s echobuiltin zeigt das gleiche Verhalten wie die externe echoDienstprogramm der Host-Plattform; Während dies von Plattform zu Plattform unterschiedlich sein kann, interpretieren die Linux- und BSD/OSX-Implementierungen nicht standardmäßig \ Escape-Sequenzen.

5

Ihr Shell-Skript muss "[email protected]" verwendet nicht [email protected]

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


ich in dem xargs Handbuch auf meiner Maschine zu sehen:

xargs liest Elemente aus der Standardeingabe , abgegrenzt durch Leerzeichen [...] oder Zeilenumbrüche

(Hervorhebung von mir)

So:

$ 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 

Mit dem ehemaligen, erhalten Sie das Äquivalent von

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

im Vergleich mit null Scheider

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

Sie müssen sich klar darüber sein, was der Begrenzer mit xargs ist, wenn die Daten Leerzeichen enthalten.

$ 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 

Beachten Sie die zusätzliche arg im letzten Fall fügt echo bereits eine neue Zeile, so dass Sie nicht ein Extra benötigen, wenn Sie echo -n

+0

Guten Rat verwenden, obwohl das eigentliche Problem liegt bei nicht zitieren '\ n' wurde an' -d' übergeben. – mklement0

+0

Das ist ein separates Problem, aber danke, dass Sie darauf hingewiesen haben. –

+1

Sie haben absolut Recht: _both_ Probleme müssen behoben werden, um das Problem zu beheben (und sie jeweils in Isolation oder Kombination das Symptom erzeugen). Ihre 'printf'-' \ 0'-'xargs -0' Lösung ist eine nette Alternative, da sie portabler ist (wird auch unter OSX funktionieren, wo 'xargs -d' nicht verfügbar ist). – mklement0