Formata a saída de xargs

9

Eu gostaria de mudar o formato dos displays xargs de saída

cat k.txt 
1 
2 
3 

e

cat k.txt | xargs 
1 2 3

No entanto, gostaria de ter 1, 2, 3 ou 1|2|3 . Alguma sugestão?

    
por Avinash 02.09.2013 / 12:10

4 respostas

15

Abaixo estão alguns exemplos de como você pode pegar um arquivo como este:

$ cat k.txt
1
2
3

e convertê-lo para este formato:

1,2,3

Você pode usar este comando para criar o arquivo acima, se quiser jogar:

$ cat <<EOF > k.txt
1
2
3
EOF

Os exemplos abaixo são divididos em dois grupos. Aqueles que "trabalham" e aqueles que "quase" trabalham. Deixo isso porque muitas vezes é tão valioso ver por que algo não funciona, como é ver por que algo acontece.

A maioria das linguagens de script que eu conheço são representadas. Alguns são representados várias vezes, já que com a famosa sigla tipicamente referenciada em Perl, TIMTOWTDI .

OBSERVAÇÃO: você pode trocar a vírgula ( , ) nos exemplos abaixo e substituí-la pelos caracteres que quiser, ou seja, | .

Exemplos que "funcionam"

Esses trechos de código produzirão a saída desejada.

O comando paste :

$ paste -s -d ',' k.txt 
1,2,3

O comando sed :

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

O comando perl :

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

O comando awk :

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

O comando python :

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

Bash's mapfile embutido:

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

O comando ruby :

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

O comando php :

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Advertências

A maioria dos exemplos acima funcionará bem. Alguns têm problemas ocultos, como o exemplo do PHP acima. A função chop() é, na verdade, um alias para rtrim() , portanto, os espaços finais da última linha também serão removidos.

O mesmo acontece com o primeiro exemplo do Ruby e o primeiro exemplo do Python. A questão é como todos estão usando um tipo de operação que basicamente "corta", cegamente, um caractere à direita. Isso está bem no exemplo que o OP forneceu, mas deve-se ter cuidado ao usar esses tipos de liners para garantir que eles estejam em conformidade com os dados que estão processando.

Exemplo

Digamos que nosso arquivo de amostra, k.txt , tenha sido assim:

$ echo -en "1\n2\n3" > k.txt

Parece semelhante, mas tem uma ligeira diferença. Não tem uma nova linha à direita ( \n ) como o arquivo original. Agora, quando executamos o primeiro exemplo do Python, recebemos isso:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Exemplos que "quase" funcionam

Estes são os "sempre uma dama de honra, nunca uma noiva" exemplos. A maioria deles provavelmente poderia ser adaptada, mas ao trabalhar uma solução potencial para um problema, quando se sente "forçada", é provavelmente a ferramenta errada para o trabalho!

O comando perl :

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

O comando tr :

$ tr '\n' ','  < k.txt 
1,2,3,

Os comandos cat + echo :

$ echo $(cat k.txt)
1 2 3

O comando ruby :

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Bashs while + read internos:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,
    
por 02.09.2013 / 12:17
4

@slm já deu uma resposta legal, mas como sua pergunta "formata saída de xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I é a opção "substituir cadeias".
  • {} é um marcador para o texto de saída.
  • Isso é semelhante ao uso de um par de chaves em "localizar".

Se você quiser se livrar do | à direita, use sed para fazer uma limpeza:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3
    
por 02.09.2013 / 12:37
0

Este é um tópico antigo, eu sei. O OP perguntou com um código simples como este. Para mantê-lo perto do original, tenho uma solução simples.

cat k.txt | xargs
1 2 3

use sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

ou

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed pode parecer um pouco estranho, mas dividido, faz muito sentido.

é para substituto. g 'é para global: sem isso, só fará a primeira substituição em cada nova linha. Desde que você usa 'xargs', ele os exibe como uma linha. Então você vai ter "1,2 3".

O delimitador é usado para separação. Eu usei o caractere /. Um truque interessante: você pode substituir o delimitador pela maioria dos outros caracteres, desde que mantenhamos o mesmo formato entre aspas. Então isso funcionaria também ....

cat k.txt | xargs | sed 's# #,#g'

ou

cat k.txt | xargs | sed 'sT T,Tg'

Obviamente, usar certos caracteres como o delimitador pode ser confuso, portanto, seja inteligente.

Espero que isso ajude alguém. Está me ajudando a aprender a ensinar essas coisas para os outros:)

    
por 21.03.2015 / 17:54
0
xargs <k.txt | tr \  \|

Você não precisa de cat - basta passar na entrada do arquivo e - se nenhum outro comando for fornecido - xargs irá passar seu formato padrão - que é de um tipo com /bin/echo 's (sem interpretações de escape c de barra invertida) .

xargs removerá o espaço em branco do cabeçalho do arquivo de entrada e comprimirá outras seqüências de espaços em branco em um único espaço. Isso significa que, ao passar o arquivo de tr para xargs , como:

tr \n \| <k.txt | xargs

... imprime ...

1|2|3|

... indo para o outro lado e operando apenas em args que xargs space-delimits faz ....

1|2|3\n

... porque xargs imprime a nova linha final (como é necessário para um arquivo de texto) , mas não recebe tr anslated dessa maneira.

Note, no entanto, que esta (ou qualquer outra solução oferecida aqui) não é responsável por xargs de cotação na entrada. xargs transmitirá literalmente caracteres de espaço em branco que não são de nova linha, simples / duplos / indexados por barra invertida, que podem ser citados como:

xargs <<\IN
1    2'      3'\'      \'4
IN
1 2      3' '4
    
por 21.03.2015 / 18:34

Tags