2016-11-26 11 views

Odpowiedz

7

Korzystanie formę decorate-sort-undecorate wzór i awk można zrobić coś takiego:

$ seq 10 | awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8- 
8 
5 
1 
9 
6 
3 
7 
2 
10 
4 

przypadku pliku, należy zrobić:

$ awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' SORTED.TXT | sort -n | cut -c8- > SHUFFLED.TXT 

lub cat plik na początku potoku.

Działa to poprzez generowanie kolumny liczb losowych między 000000 i 999999 włącznie (dekorowanie); sortowanie w tej kolumnie (sortowanie); następnie usunięcie kolumny (bez dekoracji). To powinno działać na platformach, na których sortowanie nie rozumie liczb, generując kolumnę z wiodącymi zerami do sortowania leksykograficznego.

Można zwiększyć tę randomizacji, w razie potrzeby, na kilka sposobów:

  1. Jeśli platformy sort rozumie wartości liczbowe (POSIX, GNU oraz BSD zrobić) można zrobić awk 'BEGIN{srand();} {printf "%0.15f\t%s\n", rand(), $0;}' FILE.TXT | sort -n | cut -f 2- używać w pobliżu Double pływakowy reprezentacja losowa.

  2. Jeśli są ograniczone do leksykograficznego rodzaju, po prostu połączyć dwa połączenia do rand do jednej kolumny tak: awk 'BEGIN{srand();} {printf "%06d%06d\t%s\n", rand()*1000000,rand()*1000000, $0;}' FILE.TXT | sort -n | cut -f 2- co daje kompozytowego 12 cyfr randomizacji.

+0

Nicea. Ponieważ "sort" dzieli się na wiele plików, aby przetwarzać zawartość większą niż zmieści się w pamięci (w każdym razie wersja GNU), powinno to faktycznie zadziałać. –

+0

+1 - dobry pomysł. Zauważ, że skoro "sort" wykonuje sortowanie stabilne, nie będzie to 100% perfekcyjnego tasowania: jeśli linia A występuje przed linią B na wejściu, to podejście jest nieco bardziej prawdopodobne, aby umieścić linię A przed linią B na wyjściu. Aby to naprawić, możesz odwrócić numerowanie i tasowanie, pisząc coś w stylu 'seq 10 | grep -n '' | sortuj -R | cut -d: -f2-'zamiast tego. (Ale nawet bez tej zmiany, myślę, że to prawdopodobnie w porządku: myślę, że powinno to być całkiem bliskie losowej kolejności.) – ruakh

+0

@ruakh: Dzięki. Masz rację - ma niewielką tendencję do utrzymywania porządku z powodu "sortowania" o stabilnym sortowaniu. Ma losowe cyfry od 0 do 1000000, więc byłby to problem tylko z tą samą liczbą losową w dwóch wierszach w rzędzie. Innym sposobem na uczynienie go bardziej losowym jest dodanie większej liczby cyfr lub drugiej kolumny losowych cyfr. – dawg

3

Policz linie (wc -l) i wygeneruj listę liczb odpowiadającą numerom linii, w losowej kolejności - być może poprzez wygenerowanie listy liczb w pliku tymczasowym (użyj /tmp/, która jest zwykle w pamięci RAM, a zatem stosunkowo szybko). Następnie skopiuj linię odpowiadającą każdemu z numerów do pliku docelowego w kolejności numerów przetasowanych.

Byłoby to czasowo nieefektywne ze względu na ilość poszukiwania nowych linii w pliku, ale działałoby prawie na każdym rozmiarze pliku.

0

Jak o: perl <large-input-file -lne 'print rand(), "\t", $_' | sort | perl -lpe 's/^.*?\t//' >shuffled-output-file

0

Jeśli plik jest w ciągu kilku rzędów wielkości, co zmieści się w pamięci, jedną z opcji jest losowo rozpowszechniać linie pomiędzy (powiedzmy) 1000 plików tymczasowych, a następnie losowo każdy z tych plików i złączyć wynik :

perl -we ' my $NUM_FILES = 1000; 
      my @fhs; 
      for (my $i = 0; $i < $NUM_FILES; ++$i) { 
      open $fh[$i], "> tmp.$i.txt" 
       or die "Error opening tmp.$i.txt: $!"; 
      } 
      while (<>) { 
      $fh[int rand $NUM_FILES]->print($_); 
      } 
      foreach my $fh (@fhs) { 
      close $fh; 
      } 
     ' < input.txt \ 
&& \ 
for tmp_file in tmp.*.txt ; do 
    shuf ./"$tmp_file" && rm ./"$tmp_file" 
done > output.txt 

(oczywiście będą pewne różnice w rozmiarach plików tymczasowych — nie wszystko będzie dokładnie jedna tysięczna rozmiar oryginalnego pliku — więc jeśli używasz tego podejścia , musisz dać sobie trochę bufora, wybierając z boku więcej, mniejsze pliki.)

+0

Przepraszam za wstępne błędne odczytanie - mam nadzieję, że osoba przekazująca nie ufała mojej błędnej analizie. Jest to całkowicie rozsądne podejście. –

+0

@CharlesDuffy: Bez obaw. Domyślam się, że downwizerem był l'l'l. (A nawet jeśli nie, teraz myślę, że odpowiedź dawga jest lepszym podejściem niż moje, więc nie jestem zbyt przywiązany do tej odpowiedzi. :-P) – ruakh

Powiązane problemy