Como ordenar por linha do terminal

4

Eu estava olhando para esta pergunta e eu me perguntei se o seguinte poderia ser feito a partir do terminal. Eu fiz isso em python, só quero ver se isso pode ser feito a partir do terminal, bash scripting ou qualquer outra coisa.

Suponha que eu tenha um arquivo assim:

2,4,5,14,9
40,3,5,10,1

poderia ser classificado assim, por linhas (linhas)

2,4,5,9,14
1,3,5,10,40

ou é muito complicado? Eu fiz isso usando python, eu só quero saber se isso poderia ser feito da próxima vez eu não poderia usar python. O que eu fiz foi criar listas e classificá-las.

    
por Lynob 14.04.2014 / 01:07

9 respostas

5

Aqui está outra abordagem Perl:

perl -F, -lane 'print join ",",sort {$a<=>$b} @F' file.txt

E outro shell / coreutils (embora, pessoalmente, eu prefira a excelente resposta

while read line; do 
    tr , $'\n' < <(printf -- "%s" "$line") | sort -g | tr $'\n' , | sed 's/,$/\n/';
done < file.txt
    
por terdon 14.04.2014 / 07:38
7

Isso deve ser feito com o que você está procurando. Ele lerá um arquivo (test.txt) e criará um arquivo de saída (sorted.txt) com as linhas ordenadas na mesma ordem em que aparecem no arquivo original.

while read line; do j=$(echo "$line" | sed -e 's/,/\n/g' | sort -n); echo "$j" 
    | sed -e 's/ /,/g' >> sorted.txt; done < test.txt
    
por jkt123 14.04.2014 / 02:02
4

A única dificuldade real em fazer o que você quer usando scripts de linha de comando é que a função sort disponível espera ordenar linhas dentro de um arquivo , ao invés de campos dentro de uma linha . Para contornar isso, você poderia substituir os delimitadores de campo, linha por linha, por novas linhas antes da função sort , em seguida, substituir as novas linhas por delimitadores novamente em cada linha após a classificação.

Existem vários utilitários de processamento de texto disponíveis que permitem que você faça isso (incluindo sed , awk , ou até mesmo o simples tr ), mas a própria shell bash pode fazer muito hoje em dia. Supondo que você quisesse que a entrada fosse delimitada por vírgulas (você tem uma combinação de vírgulas e delimitadores de espaço em branco no seu exemplo), você poderia fazer:

while read line; do 
  sorted=$(sort -g -- <<< "${line//,/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

Se fazer precisar lidar com delimitadores de espaço na entrada, você poderá adicioná-los como parte de uma lista de caracteres [, ] para a substituição de substring de entrada:

while read line; do 
  sorted=$(sort -g -- <<< "${line//[, ]/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

(note que a saída permanece estritamente delimitada por vírgula).

    
por steeldriver 14.04.2014 / 06:08
3

python -c "your code here" input.txt

Ou, se o seu programa tiver várias linhas e eval() for muito lento:

python yourprogram.py input.txt

Este trabalho on-line:

python -c "for l in open('input.txt'):print(','.join(sorted(l.strip().split(','), key=int)))"
    
por Cees Timmerman 14.04.2014 / 15:22
3

Usando tr e sed

Semelhante ao espírito de o que o jkt123 escreveu :

while read i; do tr , \n <<< $i | sort -n | tr \n , | sed 's/,$//'; done

Ele itera sobre as linhas e, para cada linha, substitui vírgulas por novas linhas, classifica as linhas resultantes numericamente e, em seguida, transforma as novas linhas em vírgulas. O principal problema é que isso terminará todo o resultado com uma vírgula e não com uma nova linha, que é endereçada pelo último sed. Ele remove a última vírgula e também adiciona implicitamente uma nova linha à saída.

Usando matrizes bash

Aqui está uma abordagem diferente para lidar com essa questão "junte-se a vírgulas":

while read i; do j=( $(tr , \n <<< $i | sort -n) ); ( IFS=,; echo "${j[*]}"; ); done

Ou escrito com quebra de linha:

while read i
do
   j=( $(tr , \n <<< $i | sort -n) )
   ( IFS=,; echo "${j[*]}"; )
done

Ele usa uma matriz bash para armazenar o resultado da linha classificada e faz uso da maneira como o bash expande as matrizes em literais de string usando a variável IFS special.

    
por MvG 14.04.2014 / 10:22
3

Aí vem uma solução awk ,

while read -r line; do (echo $line | awk '{ n=split(,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}') | xargs | sed -e 's/ /,/g'; done < text.txt

Explicação:

  • awk '{ n=split(,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}'

    awk Divide o campo 1 de acordo com o delimitador , e armazena cada valor na matriz a finalmente a posição superior é armazenada na variável n . Próximo asort(a) function classifica os valores da matriz. Em seguida, o loop for dentro do comando awk imprime os valores classificados no formato de registro por registro.

  • xargs | sed -e 's/ /,/g'

    xargs combina todas as linhas em uma única linha.

  • sed -e 's/ /,/g'

    Substitui os espaços por vírgulas ,

  • while read -r line;

    Todas as funções awk , xargs , sed acima são feitas linha por linha com a ajuda de while loop.

por Avinash Raj 14.04.2014 / 13:11
2

Você pode fazer isso facilmente usando perl

considere que você tem o arquivo text.txt

cat text.txt

1,5,7,8,3,6
10,34,67,1,2,0,5

Agora, o seguinte código perl classificará as linhas em text.txt

 perl -i -e 'while(<>){chomp; my @sorted = sort { $a <=> $b } split(",", $_); print join (",", @sorted); print "\n"}' text.txt

Após a classificação

cat text.txt

1,3,5,6,7,8
0,1,2,5,10,34,67
    
por Stormvirux 14.04.2014 / 03:05
2

A solução shortest usando um perl oneliner:

perl -ne 'print join(",", sort { $a <=> $b } split(/,|\n/))."\n"' text.txt
    
por Sylvain Pineau 14.04.2014 / 07:22
1

Eu também precisava dessa funcionalidade, e uma solução que encontrei é a seguinte (supondo que os dados estejam no arquivo de teste):

cat test | while read line; do echo $(echo $line | datamash -t',' transpose |sort -g| datamash -t',' transpose); done
    
por Eissa N. 05.01.2016 / 10:27