Muszla
Ładowanie języka wyższego poziomu wymaga czasu.
Dla kilku linii sama powłoka może być rozwiązaniem.
Możemy użyć polecenia zewnętrznego sort
i polecenia tr
. Jedna jest dość wydajna w sortowaniu linii, a druga skutecznie konwertuje jeden separator na nowe linie:
#!/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'
To wymaga basha z powodu użycia <<<
tylko. Jeśli to zostanie zastąpione tutaj-doc, rozwiązanie jest ważne dla posix.
Jest zdolny do sortowania pól z kartami, spacji lub znaków powłoki glob ( *
, ?
, [
). Nie nowe wiersze, ponieważ każda linia jest sortowana.
Zmień, <<<"$2"
aby <"$2"
przetwarzać nazwy plików i nazwać to tak:
shsort '.' infile
Separator jest taki sam dla całego pliku. Jeśli jest to ograniczenie, można je ulepszyć.
Jednak przetworzenie pliku zawierającego zaledwie 6000 linii zajmuje 15 sekund. Naprawdę powłoka nie jest najlepszym narzędziem do przetwarzania plików.
Awk
W przypadku więcej niż kilku wierszy (więcej niż kilku dziesiątek) lepiej jest użyć prawdziwego języka programowania. Rozwiązaniem awk może być:
#!/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
Co zajmuje tylko 0,2 sekundy dla tego samego pliku 6000 linii wspomnianego powyżej.
Zrozum, że <"$2"
pliki for można zmienić z powrotem <<<"$2"
na wiersze wewnątrz zmiennych powłoki.
Perl
Najszybszym rozwiązaniem jest 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'
Jeśli chcesz posortować zmianę pliku, <<<"$a"
po prostu "$a"
i dodać -i
opcje perla, aby edycja pliku była „na miejscu”:
#!/bin/bash
perlsort(){ perl -lpi -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' "$2"; }
perlsort '.' infile; exit