Shell
Carregar um idioma de nível superior leva tempo.
Para algumas linhas, o próprio shell pode ser uma solução.
Podemos usar o comando externo sort
e o comando tr
. Um é bastante eficiente na classificação de linhas e o outro é 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 bater por causa do uso de <<<
apenas. Se isso for substituído por um aqui-doc, a solução é válida para posix.
Isso é capaz de classificar campos com tabulações, espaços ou caracteres de globalização ( *
, ?
, [
). Não são novas linhas porque cada linha está sendo classificada.
Altere <<<"$2"
para <"$2"
para processar nomes de arquivos e chame 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 ser processado. Na verdade, o shell não é a melhor ferramenta para processar arquivos.
Awk
Por mais de algumas linhas (mais do que alguns 10), é melhor usar uma linguagem de programação real. Uma solução awk poderia 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 <"$2"
para arquivos pode ser alterado de volta para <<<"$2"
para linhas dentro de variáveis do shell.
Perl
A solução mais rápida é o 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ê quiser classificar uma alteração de arquivo <<<"$a"
para simplesmente "$a"
e adicionar -i
às opções perl para tornar a edição de arquivo "no lugar":
#!/bin/bash
perlsort(){ perl -lpi -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' "$2"; }
perlsort '.' infile; exit