Convertendo stdout para raw-data não aceitando várias palavras usando xargs e encanamento

2
Em primeiro lugar peço desculpas pelo título gore, estou lutando por uma boa maneira de resumir esta questão. De qualquer forma, tenho passado várias coisas para funções usando xargs e estou me deparando com um problema estranho.

No momento, estou executando o comando: echo "hello world" | xargs curl http://localhost:8080/function/func_wordcount -d" , que recebe o stdout de echo "hello world" e, em seguida, canaliza para func_wordcount usando a opção -d . A opção -d é para enviar dados brutos e meu func_wordcount recebe a entrada de dados brutos e imprime o número de palavras e o número de letras.

Por exemplo, quando eu escrevo echo "hello" | xargs curl http://localhost:8080/function/func_wordcount -d" , a saída é: 1, 5 significando que havia uma palavra que continha 5 letras.

No entanto, quando tento incluir muitas palavras, recebo um erro. Quando escrevo echo "hello world" | xargs curl http://localhost:8080/function/func_wordcount -d" , obtenho a saída 1, 5 e, em seguida, uma nova linha com o erro: curl: (6) could not resolve host: world . Portanto, tenho certeza de que ele está dividindo o hello world em duas palavras quando eu converter o stdout em dados brutos usando a opção -d .

Além disso, apenas para mostrar que a função funciona sem canalizar e converter, quando executo minha função com apenas curl http://localhost:8080/function/func_wordcount -d "hello world" , obtenho 2, 11 mostrando que há duas palavras e 11 caracteres.

Minha pergunta é como solucionar esse problema de divisão. A parte que eu acho confusa é por que ela está analisando apenas a primeira metade da entrada e completando isso, e então lançando um erro na segunda parte ao invés de apenas enviar um pedaço de dados. Eu só fui capaz de enviar entrada que não é delimitada por espaços de modo que os usos das funções se tornam muito limitados. Qualquer ajuda é apreciada.

    
por cjnash 17.05.2018 / 17:22

2 respostas

2

Isso é o que é xargs . Ele pega uma lista de palavras (em branco ou em nova linha separadas, também compreendendo alguma forma de citar) em seu stdin e passa elas como argumentos para o (s) comando (s) que executa.

Aqui, se você quiser passar hello word como um argumento para curl , será necessário:

echo '"hello world"' | xargs curl...

Em que xargs entende os "..." como um mecanismo de cotação para evitar que o espaço entre hello e world seja tratado como um separador de argumentos. xargs também entende \ e '...' (de maneiras diferentes de shells POSIX).

Com o GNU xargs , você também pode especificar o delimitador. Por exemplo com:

echo hello world | xargs -d '\n' curl...

Apenas nova linha seria entendida como delimitadora (não em branco) e os mecanismos de cotação desativados.

Isso permite que você passe o conteúdo de cada linha (em oposição a cada palavra) como argumento para o comando.

Embora -d raramente seja suportado fora do GNU xargs , -0 , outra de suas extensões (para delimitar NULs e desativar o processamento de cotações) é mais amplamente suportada. Então você também pode fazer:

echo hello world | tr '\n' '
echo hello world | xargs -I@@ curl... @@
' | xargs -0 curl...

Se houver várias linhas de entrada, xargs passará todas elas como argumentos separados para curl . Se você quiser chamar um curl para cada linha, você pode adicionar uma opção -n 1 .

Você também pode usar:

echo '"hello world"' | xargs curl...

Isso chama um curl para cada linha, mas observe que os espaços em branco iniciais são eliminados e xargs ainda faz algum processamento de cotação, portanto, deve ser evitado para dados arbitrários.

    
por 17.05.2018 / 17:33
2

Na página de manual do GNU xargs :

xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command one or more times with any initial-arguments followed by items read from standard input.

i.e. o comportamento padrão é que qualquer espaço em branco na entrada atua como um separador, portanto hello world resulta em dois argumentos.

Se você quiser que os xargs mantenham as linhas inteiras intactas, use 'xargs -d' \ n '(em GNU xargs, não me lembro dos outros).

No entanto, isso ainda resultaria em uma entrada de várias linhas, fornecendo seus curl de vários argumentos. Se você quiser evitar isso e executar o comando curl uma vez para cada linha de entrada, use xargs -d '\n' -n 1 .

Se a sua entrada contiver apenas uma linha, você também pode usar a substituição de comando em vez do canal:

curl http://... -d "$(echo "hello world")"
    
por 17.05.2018 / 17:33

Tags