Concha
Carregar um idioma de nível superior leva tempo.
Por algumas linhas, o próprio shell pode ser uma solução.
Podemos usar o comando externo sort
e do comando tr
. Uma é bastante eficiente na classificação de linhas e a outra é eficaz para converter um delimitador em novas linhas:
#!/bin/bash
shsort(){
while IFS='' read -r line; do
echo "$line" | tr "$1" '\n' |
sort -n | paste -sd "$1" -
done <<<"$2"
}
shsort ' ' '10 50 23 42'
shsort '.' '10.1.200.42'
shsort ',' '1,100,330,42'
shsort '|' '400|500|404'
shsort ',' '3 b,2 x,45 f,*,8jk'
shsort '.' '10.128.33.6
128.17.71.3
44.32.63.1'
Isso precisa do bash por causa do uso de <<<
only. Se isso for substituído por um documento aqui, a solução é válida para o posix.
Este é capaz de classificar campos com tabulações, espaços ou caracteres shell glob ( *
, ?
, [
). Não novas linhas porque cada linha está sendo classificada.
Mude <<<"$2"
para <"$2"
para processar nomes de arquivos e chame-o como:
shsort '.' infile
O delimitador é o mesmo para o arquivo inteiro. Se isso é uma limitação, pode ser melhorado.
No entanto, um arquivo com apenas 6000 linhas leva 15 segundos para processar. Na verdade, o shell não é a melhor ferramenta para processar arquivos.
Awk
Por mais do que algumas linhas (mais do que algumas dez), é melhor usar uma linguagem de programação real. Uma solução awk pode ser:
#!/bin/bash
awksort(){
gawk -v del="$1" '{
split($0, fields, del)
l=asort(fields)
for(i=1;i<=l;i++){
printf( "%s%s" , (i==0)?"":del , fields[i] )
}
printf "\n"
}' <"$2"
}
awksort '.' infile
O que leva apenas 0,2 segundos para o mesmo arquivo de 6000 linhas mencionado acima.
Entenda que os <"$2"
arquivos for podem ser alterados novamente <<<"$2"
para linhas dentro de variáveis do shell.
Perl
A solução mais rápida é perl.
#!/bin/bash
perlsort(){ perl -lp -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' <<<"$2"; }
perlsort ' ' '10 50 23 42'
perlsort '.' '10.1.200.42'
perlsort ',' '1,100,330,42'
perlsort '|' '400|500|404'
perlsort ',' '3 b,2 x,45 f,*,8jk'
perlsort '.' '10.128.33.6
128.17.71.3
44.32.63.1'
Se você deseja classificar um arquivo, mude <<<"$a"
para simplesmente "$a"
e adicione -i
às opções perl para tornar a edição do arquivo "no lugar":
#!/bin/bash
perlsort(){ perl -lpi -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' "$2"; }
perlsort '.' infile; exit