xargs substitution de plus d'un argument

2

Par défaut xargs concaténera de nombreuses lignes de son entrée et passera ensuite à la commande spécifiée. Par exemple:

echo -e 'line 1\nline 2\nline 3' | xargs echo 

résulte en

line 1 line 2 line 3

Puisque les arguments sont envoyés à une seule commande echo (dans les limites de la longueur de la ligne de commande).

Parfois, vous souhaitez utiliser une chaîne de remplacement pour placer les arguments ailleurs dans la commande, plutôt que la fin:

echo -e 'line 1\nline 2\nline 3' | xargs -Ix echo x DONE
line 1 DONE
line 2 DONE
line 3 DONE

À présent, xargs n'a substitué qu'un argument à chaque invocation d'écho, car comme le dit la page de manuel "-I implique -L 1 ...". C’est probablement le bon comportement pour un cas typique, mais existe-t-il un moyen de le remplacer, alors je reçois line 1 line 2 line 3 DONE comme sortie?

Veuillez noter que mon exemple est uniquement illustratif - je ne suis pas très intéressé par les moyens non xargs de traiter ce problème.

BeeOnRope
la source

Réponses:

2

Je ne sais pas d'un xargs option qui le fera, mais vous pouvez obtenir quelque chose de similaire avec une invocation de bash -c:

$ echo -e "line 1\nline    2\nline 3" | xargs bash -c 'echo "${@}" DONE' _
line 1 line 2 line 3 DONE

Notez que xargs ne fournit pas le lignes comme arguments, même si vous spécifiez -L. Vous voudrez peut-être utiliser -d pour spécifier que new-line sépare les éléments (gnu xargs uniquement, je crois). Contrastez ce qui suit:

$ echo -e "line 1\nline    2\nline 3" |
  xargs bash -c 'printf "<%s>\n" "${@}" DONE' _
<line>
<1>
<line>
<2>
<line>
<3>
<DONE>

$ echo -e "line 1\nline    2\nline 3" |
  xargs -d\\n bash -c 'printf "<%s>\n" "${@}" DONE' _
<line 1>
<line    2>
<line 3>
<DONE>
rici
la source
Le bon point sur la façon dont xargs divise les arguments, sur des limites d'espaces, et non de lignes (bien que les lignes soient spéciales pour des arguments tels que -L et donc implicitement pour -I).
BeeOnRope
@BeeOnRope: même avec -L, xargs casse les arguments dans l'espace de mots. Le nombre de lignes spécifie le nombre de lignes contenant des arguments, mais les lignes ne sont pas traitées autrement.
rici
C’est pourquoi j’ai dit "les lignes sont spéciales", non pas que xargs change la façon dont il divise les arguments, mais qu’il utilise les lignes pour répartir initialement les entrées dans les invocations, puis procède à la décomposition habituelle.
BeeOnRope
echo -e "ligne 1 \ n ligne 2 \ n ligne 3" | écho parallèle: {}:
Ole Tange
1

Convertir les nouvelles lignes en \nul terminateurs, puis utilisez xargs -0

$ echo -ne 'line 1\nline 2\nline 3\n' | tr '\n' '\0' | xargs -0 -Ix echo x DONE
line 1 DONE
line 2 DONE
line 3 DONE
hroptatyr
la source
Comme ci-dessus, j'ai déjà la même sortie sans les tr et -0 (ce n'est pas nécessaire ici). Le problème est que je veux tout sur une seule ligne: line 1 DONE line 2 DONE ...
BeeOnRope
-1

Si je comprends votre question, je pense que vous voulez simplement convertir les nouvelles lignes en non-délimiteur.

echo -ne 'foo \ nbar \ nbaz' | tr '\ n' '' | xargs -I {} echo {} TERMINÉ

user1093043
la source
Non, je veux que foo, bar et baz soient des arguments uniques. L'exemple est artificiel - le but est de pouvoir mettre quelque chose après les arguments ajoutés par xargs.
BeeOnRope
C'est ce que vous obtiendrez. Par exemple, ls | tr '\n' ' ' | xargs -I{} echo {} DONE les rendements dir1/ dir2/ dir3/ DONE.
user1093043
Non, dans ce cas, la chaîne entière "dir1 / dir2 / dir3 /" est transmise comme un seul argument à echo, ce qui n'est pas ce que je veux. Oui, le résultat est le même dans mon exemple de jouet, mais dans la vraie vie, je ne passe pas à l'écho. Essayez votre exemple en le passant à une version de echo qui cite tous les arguments (par exemple) et vous verrez la différence.
BeeOnRope
Alors ce que vous voulez ne peut pas être fait uniquement avec les options xargs, je ne pense pas. (En outre, même si je vois ce que vous voulez dire maintenant, il n’est pas très clair que c’est ce que vous voulez faire de votre message original, à cause de l’exemple que vous avez inclus).
user1093043