Como dar uma lista separada por vírgula como argumentos para o próximo comando

8

Eu tenho um script s1 que gera uma lista de números separados por ',' %código%. Agora eu quero dar esses números para script 1,2,3,4 como argumentos, de modo que s2 será executado em cada um deles e saída seu resultado em uma linha separada. Por exemplo, se s2 multiplica números por dois, esse seria o resultado que estou procurando:

2
4
6
8

O que estou fazendo agora é:

s1 | xargs -d "," | xargs -n1 s2

Mas eu sinto que estou fazendo isso de uma maneira tão tola! Então minha pergunta é:

Qual é a maneira correta de fazer isso?

Meu problema com a minha solução é que ela está chamando xargs duas vezes e iterando sobre a entrada duas vezes, o que não é razoável para os meus olhos, é claro, por meio de desempenho! A resposta s2 parece boa, mas não tenho certeza se é apenas uma iteração uma vez. Em caso afirmativo, verifique isso em sua resposta e eu a aceitarei. A propósito, eu prefiro não usar o Perl, pois ele ainda está fazendo iteração duas vezes e também o Perl pode não existir em muitos sistemas.

    
por yukashima huksay 18.12.2017 / 16:06

3 respostas

15

Isso também deve funcionar da mesma maneira:

s1 | xargs -d "," -n1 s2

Caso de teste:

printf 1,2,3,4 | xargs -d ',' -n1 echo

Resultado:

1
2
3
4

Se s1 gerar essa lista seguida por um caractere de nova linha, você poderá removê-la, caso contrário, a última chamada será com 4\n em vez de 4 :

s1 | tr -d '\n' | xargs -d , -n1 s2
    
por 18.12.2017 / 16:14
6

Se s2 puder aceitar vários argumentos, você poderá:

(IFS=,; ./s2 $(./s1))

que temporariamente substitui o IFS por vírgula, tudo em um subshell, de modo que s2 veja a saída de s1 dividida por vírgulas. O subshell é uma forma abreviada de alterar o IFS sem salvar o valor anterior ou redefini-lo.

Uma versão anterior desta resposta estava incorreta, provavelmente devido a uma configuração do IFS restante, corrompendo os resultados. Obrigado ao ilkkachu por apontando meu erro .

Para percorrer as saídas manualmente e fornecê-las individualmente para s2 , aqui demonstrando o saving & redefinindo o IFS:

oIFS="$IFS"
IFS=,
for output in $(./s1); do ./s2 "$output"; done
IFS="$oIFS"

ou execute os bits IFS em um subshell como antes:

(
IFS=,
for output in $(./s1); do ./s2 "$output"; done
)
    
por 18.12.2017 / 18:34
1

Tente isto:

s1 | perl -pe 's/,/\n/g' | xargs -n1 s2
    
por 18.12.2017 / 16:13