Red Hat Linux'ta standart araçları kullanarak bir dosyadaki satırları nasıl rastgele hale getirebilirim?


102

Red Hat Linux'ta standart araçları kullanarak bir dosyadaki satırları nasıl rastgele hale getirebilirim?

shufKomuta sahip değilim, bu yüzden aynı görevi yerine getiren bir perlveya awktek astar gibi bir şey arıyorum .


1
Neredeyse aynı soruyu sordum [ stackoverflow.com/questions/286640/…
Steve Schnepp


Gcc'yi herhangi bir linux için standart bir araç olarak görüyorum. ; D
msb

Yanıtlar:


64

Ve bir Perl tek astar alacaksınız!

perl -MList::Util -e 'print List::Util::shuffle <>'

Bir modül kullanır, ancak modül Perl kod dağıtımının bir parçasıdır. Bu yeterince iyi değilse, kendi oyununuzu yuvarlamayı düşünebilirsiniz.

-iDosyayı düzenlemesini sağlamak için bunu bayrakla ("yerinde düzenle") kullanmayı denedim . Belgeler, çalışması gerektiğini gösteriyor, ancak işe yaramıyor. Karıştırılan dosyayı hala standart çıktı olarak görüntüler, ancak bu sefer orijinali siler. Kullanmamanı öneririm.

Bir kabuk betiğini düşünün:

#!/bin/sh

if [[ $# -eq 0 ]]
then
  echo "Usage: $0 [file ...]"
  exit 1
fi

for i in "$@"
do
  perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
  if [[ `wc -c $i` -eq `wc -c $i.new` ]]
  then
    mv $i.new $i
  else
    echo "Error for file $i!"
  fi
done

Test edilmedi, ama umarım işe yarar.


Orijinal dosyayı yedeklemek için, -i bayrağına bir uzantı ekleyebilirsiniz [ perldoc.perl.org/perlrun.html]
Steve Schnepp

Genellikle bir Perl hayranıyım, ama daha kısa olmanın yararı vardır bu yakut örnek geldi: ruby -e 'puts STDIN.readlines.shuffle'. Hızın karşılaştırılabilir olup olmadığını görmek için büyük girdiler üzerinde test edilmesi gerekir. (OS X'te de çalışır)
mivk

aşağıdaki yorum başına, shufher şeyi belleğe yükler, bu nedenle gerçekten büyük bir dosyayla çalışmaz (benimki ~ 300GB tsv'dir). Bu perl betiği benimkinde de başarısız oldu, ancak dışında hata yok Killed. Perl çözümünün her şeyi belleğe de yükleyip yüklemediğine dair bir fikriniz var mı yoksa karşılaştığım başka bir sorun var mı?
seth127

211

Um, unutmayalım

sort --random-sort

1
Pekala, gnu-coreutils 7.1 (standart gentoo kurulumu) kullanıyorum, bu seçenekle sıralama var, ne zaman göründüğünden veya başka uygulamalarda olup olmadığından emin değilim.
Jim T

1
Özellik 10 Aralık 2005 tarihinde yapıldı, sonraki sürüm 5.94 idi, bu yüzden o sürümden beri mevcut olduğunu tahmin ediyorum.
Jim T

41
OS X'de gnu coreutils'i homebrew ile kurabilirsiniz: brew install coreutilsTüm yardımcı programların başında ag bulunur yani: gsort --random-sortveya gshufbeklendiği gibi çalışacaktır
mike

3
+1 @mike. Macports kullanıyorum ve yaptığımda da kurdum gsortve gshufyükledimport install coreutils
Noah Sussman

10
Bu çözüm, yalnızca satırlarınızın tekrarı yoksa iyidir. Yaparlarsa, bu çizginin tüm örnekleri yan yana görünecektir. shufBunun yerine (linux üzerinde) kullanmayı düşünün .
Ali J

119

shuf en iyi yoldur.

sort -Racı verici derecede yavaş. Sadece 5GB dosyasını sıralamayı denedim. 2,5 saat sonra pes ettim. Sonra shufbir dakika içinde sıraladı.


Bu harika. GNU çekirdeklerinde olduğu görülüyor.
ariddell

4
sort -RNedenin yavaş olduğundan şüpheleniyorum, her satır için bir hash hesaplıyor. Dokümanlardan: " Giriş anahtarlarına hash uygulayarak ve ardından hash değerlerini sıralayarak sıralayın. "
Joe Flynn

14
dikkat, shufher şeyi belleğe yükler.
jfs

1
@benroth: Söyleyebileceğim kadarıyla, gerçekten büyük girdi sayıları ile belleği arttırmak biraz yardımcı olabilir , ancak yine de genel olarak yavaş. Testlerimde, ile oluşturulan 1 milyon satırlık bir girdi dosyasını sıralamak , ne kadar bellek ayırdığım önemli değil, işlemek seq -f 'line %.0f' 1000000için aynı, uzun zaman aldı (ile olduğundan çok, çok daha uzun shuf).
mklement 0

1
@ mklement0, haklısın! Daha önce sahip olduğumdan çok daha büyük bir dosya ile denedim ve hashing gerçekten de bir darboğaz gibi görünüyor.
benroth

23
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-

Dosyayı okuyun, her satırın başına rastgele bir sayı ekleyin, dosyayı bu rastgele öneklere göre sıralayın, daha sonra önekleri kesin. Herhangi bir yarı modern kabukta çalışması gereken tek astar.

DÜZENLEME: Richard Hansen'ın görüşlerini içeriyor.


1
Bu işe yarar ve yaratıcı bir çözümdür, ancak satırlardaki baştaki boşlukları silecektir.
Chris Lutz

@Chris son kesimi | sed 's / ^ [^ \ t] * \ t //' olarak değiştirerek bunu düzeltmeli
bdonlan

Yaklaşımın sadeliğine şeref!
Shashikant Kore

3
POSIX uyumluluğu için +1 (hariç $RANDOM), ancak verileri parçalamak için -1. Değiştirme while read file while IFS= read -r fengeller readkaldırma ön ve boşluk arka den (bakınız bu yanıt ) ve tersbölülerden işleme önler. Sabit uzunlukta rastgele bir dizge kullanmak, cutbaştaki boşluğun silinmesini engeller . Sonuç: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen

3
@Richard Hansen: Teşekkürler, önerilen bu değişiklikler kesinlikle uygun, yazımı düzenledim.
ChristopheD

9

Python için tek satırlık bir:

python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile

Ve sadece tek bir rastgele satır yazdırmak için:

python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile

Ama bakın bu yazı piton en dezavantajlarından için random.shuffle(). Birçok (2080'den fazla) öğeyle iyi çalışmayacaktır.


5

Jim'in cevabıyla ilgili:

My ~/.bashrcaşağıdakileri içerir:

unsort ()
{
    LC_ALL=C sort -R "$@"
}

GNU coreutils'in sort, -R= --random-sortile her satır için rastgele bir hash oluşturur ve ona göre sıralar. Rastgele hash, bazı eski (hatalı) sürümlerde bazı yerel ayarlarda kullanılmaz ve normal sıralı çıktı döndürmesine neden olur, bu yüzden ayarladım LC_ALL=C.


Chris'in cevabıyla ilgili:

perl -MList::Util=shuffle -e'print shuffle<>'

biraz daha kısa tek astarlıdır. ( -Mmodule=a,b,ckısaltmasıdır -e 'use module qw(a b c);'.)

Basit vermenin nedeni -i, yerinde karıştırmak için işe yaramıyor çünkü Perl print, dosyanın okunduğu aynı döngüde gerçekleşmesini beklemesi ve print shuffle <>tüm girdi dosyaları okunup kapatılana kadar çıktı vermemesidir.

Daha kısa bir çözüm olarak,

perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'

dosyaları yerinde karıştırır. ( -n"kodu bir while (<>) {...}döngüye sarmak ; BEGIN{undef$/}Perl'in bir seferde satırlar yerine tek seferde dosyalar üzerinde çalışmasını sağlar ve dolaylı olarak satırlar yerine tam bir dosya ile yapıldığı split/^/miçin gereklidir $_=<>.)


-R sıralaması OS X'te yoktur, ancak bazı harika Perl yanıtları ve genel olarak harika bir yanıt için +1 vardır.
Chris Lutz

GNU coreutils'i OS X'e yükleyebilirsiniz, ancak (geçmişte yaptığım gibi) yerleşik araçları kırmamaya dikkat etmelisiniz ... Bununla birlikte OP, kesinlikle GNU'ya sahip olan Redhat Linux üzerinde. coreutils standardı.
ephemient

3

Coreutils'i homebrew ile kurduğumda

brew install coreutils

shufolarak kullanılabilir hale gelir n.


brew, tüm komutların önüne geçti, gböylece benim için shufoldu gshuf.
Jörn

^ Bu, POSIX olmadıkları için mi yoksa tamamen kapalı mıyım?
Dave Liu

1

DarwinPorts ile Mac OS X:

sudo port install unsort
cat $file | unsort | ...

1

FreeBSD'nin kendi rastgele programı vardır:

cat $file | random | ...

/ Usr / games / random içinde, bu yüzden oyun yüklemediyseniz, şansınız yok.

Textproc / rand veya textproc / msort gibi bağlantı noktalarını kurmayı düşünebilirsiniz. Taşınabilirlik önemliyse, bunlar Linux ve / veya Mac OS X'te mevcut olabilir.



-1

Veya MacPorts'tan edinin:

$ sudo port install coreutils

ve / veya

$ /opt/local//libexec/gnubin/sort --random-sort
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.