Sortowanie bloków linii

12

Mam plik zawierający 4n wierszy. Oto fragment zawierający 8 wierszy

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

Chcę posortować blok, w którym każdy blok składa się z 4 linii opartych na pierwszej kolumnie. Dane wyjściowe fragmentu powinny wyglądać tak, jak pokazano poniżej.

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 
Meenakshi
źródło

Odpowiedzi:

16

Jedną z opcji jest użycie do dodania początkowego prefiksu numeru seryjnego co N linii (N = 4 w twoim przypadku). Następnie wprowadź prefiks jako podstawową kolumnę sortującą do sort.

Przykład z N = 4:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '
iruvar
źródło
7

Jeśli jest to jednorazowy problem i nie chcesz uczyć się Pythona, Perla lub awk, możesz użyć podstawowych poleceń spliti sortpoleceń.

Najpierw podziel plik na 4 liniowe fragmenty z -l opcją:

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

Te sort -nrodzaje względem wartości numerycznych pierwszej kolumny (999 przed 1234). -a 6powinien zająć się plikiem z 26 ^ 6 * 4 liniami. my_prefix_powinno być czymś unikalnym dla katalogu, z którym pracujesz.

Anthon
źródło
3

Możesz to zrobić za pomocą Perla:

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

Jak to działa

  • -n-> uruchom kod dla każdej linii wejściowej (i wstaw bieżącą linię $_)
  • -l -> dodaj nowy wiersz do wyniku dowolnego print
  • -e -> wykonaj następujący ciąg jako kod Perla
  • Każda linia jest dołączana do tablicy @a.
  • $.przechowuje bieżący numer linii i jeśli ta liczba nie jest zgodna z zerowym modułem 4, to kontynuujemy pracę. Jeśli jest zgodny z zerowym modułem 4, osiągnęliśmy linię, której liczba jest wielokrotnością 4 (koniec bloku), w którym to przypadku sortujemy wpisy w @aporządku rosnącym numerycznie i drukujemy wpisy w posortowanej tablicy połączone nową linią ze standardowym wyjściem.
Joseph R.
źródło
2

Używając powłoki podobnej do Bourne'a,

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data
200_sukces
źródło
2

Oto kilka „czystych” awkrozwiązań:

Jeśli indeksy mają zawsze tę samą sekwencję rosnącą (6115-6119), co w danych przykładowych, można użyć algorytmicznego „skrótu”:

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

To robi

  • Dodaj wszystkie linie do tablicy a, rozmieszczone w pozycjach indeksu 6115-6119
  • W każdej czwartej linii ( !(NR%4)) przeglądaj zawartość tablicy, aby drukować w żądanej kolejności.

Jeśli indeksy liczbowe są zawsze tymi samymi czterema, ale nie rosnącą sekwencją liczb całkowitych, musisz posortować:

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

Uwaga: dotyczy GNU awk, inne mogą nie obsługiwać asort.


Jeśli każdy blok czterech może mieć różne identyfikatory numeryczne:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

Uwaga: TIL z @Gilles self-answer (+2) to użycie deletenie jest (jeszcze) POSIX, ale powszechnie obsługiwane .


Wersja z prawidłowym użyciem ™ delete:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

Wersja bez usuwania, wykorzystująca więcej pamięci i wymiarów:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}
Alex Stragies
źródło
1

Możesz uzyskać czyste rozwiązanie za pomocą R. Jeśli powyższa tabela znajduje się w pliku o nazwie „table.txt”, wykonaj następujące czynności. Pożądany wynik będzie w pliku „tableout.txt”.

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

Zobacz również Jak sortować według kolumny dataframe (e) R .

Faheem Mitha
źródło