Substituição de xargs de mais de um argumento

2

Por padrão xargs irá concatenar muitas linhas de sua entrada e passar então para o comando especificado. Por exemplo:

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

resulta em

line 1 line 2 line 3

Já que os argumentos são enviados para um único comando de eco (dentro dos limites do comprimento da linha de comando).

Às vezes, você quer usar a string de substituição para colocar os argumentos em outro lugar no comando, em vez do final:

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

Agora, os xargs só substituem um argumento por cada chamada de eco, porque, como diz a página man, "-I implica -L 1 ...". Esse é provavelmente o comportamento certo para um caso típico, mas existe alguma maneira de substituí-lo, então eu recebo line 1 line 2 line 3 DONE como a saída?

Por favor, note que o meu exemplo é apenas ilustrativo - não estou muito interessado em maneiras não-xargs de abordar esta questão.

BeeOnRope
fonte

Respostas:

2

Eu não sei de um xargs opção que vai fazer isso, mas você pode conseguir algo semelhante com uma invocação de bash -c:

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

Observe que xargs não fornece o linhas como argumentos, mesmo se você especificar -L. Você pode querer usar -d para especificar que a nova linha separa itens (apenas gnu xargs, acredito). Compare o seguinte:

$ 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
fonte
Bom ponto sobre como o xargs está dividindo argumentos, em limites de espaço em branco, não limites de linha (embora linhas sejam especiais para argumentos como -L e, portanto, implicitamente para -I).
BeeOnRope
@BeeOnRope: mesmo com -L, xargs quebra argumentos no espaço de palavras. A contagem de linhas especifica o número de linhas contendo argumentos, mas as linhas não são tratadas de outra forma especialmente.
rici
Certo, é por isso que eu disse "as linhas são especiais" não que o xargs mude a forma como ele quebra os argumentos, mas que ele usa linhas para inicialmente dividir a entrada em invocações, e então começa a se fragmentar no espaço em branco como de costume.
BeeOnRope
echo -e "linha 1 \ nline 2 \ nline 3" | eco paralelo: {}:
Ole Tange
1

Converter novas linhas em \nul terminadores, então use 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
fonte
Como acima, eu tenho a mesma saída já sem o tr e -0 (não é necessário aqui). A questão é que eu quero tudo em uma linha: line 1 DONE line 2 DONE ...
BeeOnRope
-1

Se eu entendi sua pergunta, acho que você só quer converter novas linhas para um não delimitador.

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

user1093043
fonte
Não, eu quero que cada um de foo, bar e baz seja argumentos únicos. O exemplo é artificial - o ponto é poder colocar algo depois de os argumentos adicionados por xargs.
BeeOnRope
Isso é o que você vai conseguir. Por exemplo, ls | tr '\n' ' ' | xargs -I{} echo {} DONE rendimentos dir1/ dir2/ dir3/ DONE.
user1093043
Não, nesse caso, a string inteira "dir1 / dir2 / dir3 /" é passada como um único argumento para eco, que não é o que eu quero. Sim, a saída é a mesma no meu exemplo de brinquedo, mas na vida real eu não estou passando para ecoar. Tente o seu exemplo, mas passando-o para uma versão do eco que cite todos os argumentos (por exemplo) e você verá a diferença.
BeeOnRope
Então o que você quer não pode ser feito apenas com opções xargs, eu não acho. (Além disso, embora eu veja o que você quer dizer agora, não está muito claro que isso é o que você pretende do seu post original, dado o exemplo que você inclui).
user1093043