麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > Linux Shell > 正文

Shell腳本實現亂序排列文件內容的多種方法(洗牌問題)

2020-07-27 19:08:52
字體:
來源:轉載
供稿:網友

洗牌問題:洗一副撲克,有什么好辦法?既能洗得均勻,又能洗得快?即相對于一個文件來說怎樣高效率的實現亂序排列?

ChinaUnix 確實是 Shell 高手云集的地方,只要你想得到的問題,到那里基本上都能找到答案。r2007 給出了一個取巧的方法,利用 Shell 的 $RANDOM 變量給原文件的每一行加上隨機的行號然后根據這個隨機行號進行排序,再把臨時加上去的行號給過濾掉,這樣操作之后得到的新文件就相當于被隨機“洗”了一次:

復制代碼 代碼如下:

while read i;do echo "$i $RANDOM";done<file|sort -k2n|cut -d" " -f1

當然如果你的源文件每行的內容比較復雜的話就必須對這段代碼進行改寫,但只要知道了處理的關鍵技巧,剩下的問題都不難解決。

另外一篇來自蘇蓉蓉的用 awk 來實現洗牌效果的隨機文件排序代碼分析(原貼在這里,以及對此帖的一個后續討論,如果你沒有登錄帳號的話可以到這里查看精華區文章)則寫的更為詳細:
--------------------------------------------------------------------
關于洗牌問題,其實已經有了一個很好的shell解法,這里另外給三個基于AWK的方法,有錯誤之處還請不吝指出。

方法一:窮舉

類似于窮舉法,構造一個散列來記錄已經打印行出現行的次數,如果出現次數多于一次則不進行處理,這樣可以防止重復,但缺點是加大了系統的開銷。

復制代碼 代碼如下:

awk -v N=`sed -n '$=' data` '
BEGIN{
FS="/n";
RS=""
}
{
srand();
while(t!=N){
  x=int(N*rand()+1);
  a[x]++;
  if(a[x]==1)
    {
        print $x;t++
    }
  }
}
' data

方法二:變換

基于數組下標變換的辦法,即用數組儲存每行的內容,通過數組下標的變換交換數組的內容,效率好于方法一。

復制代碼 代碼如下:

#! /usr/awk

BEGIN{
srand();
}

{
b[NR]=$0;
}

END{

C(b,NR);
for(x in b)
  {
    print b[x];
  }}

function C(arr,len,i,j,t,x){

for(x in arr)
  {
      i=int(len*rand())+1;
      j=int(len*rand())+1;
      t=arr[i];
      arr[i]=arr[j];
      arr[j]=t;
  }

}


方法三:散列

    三個方法中最好的。
    利用AWK中散列的特性(詳細請看:info gawk 中的7.x ),只要構造一個隨機不重復的散列函數即可,因為一個文件每行的linenumber是獨一無二的,所以用:

    隨機數+每行linenumber    ------對應------>    那一行的內容

    即為所構造的隨機函數。
    從而有:

復制代碼 代碼如下:

awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data

    其實大家擔心的使用內存過大的問題不必太在意,可以做一個測試:

測試環境:

PM 1.4GHz CPU,40G硬盤,內存256M的LAPTOP
SUSE 9.3  GNU bash version 3.00.16 GNU Awk 3.1.4

產生一個五十幾萬行的隨機文件,大約有38M:

復制代碼 代碼如下:

od /dev/urandom |dd  count=75000 >data

拿效率較低的方法一來說:

洗牌一次所用時間:

復制代碼 代碼如下:

time awk -v N=`sed -n '$=' data` '
BEGIN{
FS="/n";
RS=""
}
{
srand();
while(t!=N){
  x=int(N*rand()+1);
  a[x]++;
  if(a[x]==1)
    {
        print $x;t++
    }
  }
}
' data

結果(文件內容省略):
復制代碼 代碼如下:

real    3m41.864s
user    0m34.224s
sys     0m2.102s

所以效率還是勉強可以接受的。

方法二的測試:

復制代碼 代碼如下:

time awk -f awkfile datafile

結果(文件內容省略):
復制代碼 代碼如下:

real    2m26.487s
user    0m7.044s
sys     0m1.371s

效率明顯好于第一個。

接著考察一下方法三的效率:

復制代碼 代碼如下:

time awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data

結果(文件內容省略):
復制代碼 代碼如下:

real    0m49.195s
user    0m5.318s
sys     0m1.301s

對于一個38M的文件來說已經相當不錯了。
--------------------------------------------------------------------

附帶存一個來自 flyfly 寫的 python 版本亂序代碼:

復制代碼 代碼如下:

#coding:gb2312
import sys
import random

def usage():
print "usage:program srcfilename dstfilename"
global filename
filename = ""
try:
filename = sys.argv[1]
except:
usage()
raise()
#open the phonebook file

f = open(filename, 'r')
phonebook = f.readlines()
print phonebook
f.close()

#write to file randomly
try:
filename = sys.argv[2]
except:
usage()
raise()

f = open(filename, 'w')
random.shuffle(phonebook)
f.writelines(phonebook)
f.close()

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 精品国产一区二区三 | 亚洲一区二区在线 | 久久成人综合网 | 一色桃子av大全在线播放 | 日韩毛片一区二区三区 | 美女视频大全网站免费 | 国产69精品久久久久99尤 | 久久久久一区二区三区四区五区 | 少妇的肉体2无删减版 | 最新亚洲国产 | 久久九九热re6这里有精品 | 国产精品二区高清在线 | 亚洲国产高清一区 | 欧美成人免费电影 | 午夜视频在线观看免费视频 | 国产亚洲综合一区二区 | 亚洲伊人色欲综合网 | 高清国产在线 | av电影免费观看 | 亚洲精品久久久久久久久久 | 毛片一级免费看 | 99精品国产视频 | 欧美一区二区三区久久精品视 | 影视免费观看 | 国产精品一区二区三区在线播放 | 一区二区三区日韩电影 | 久久久久久久免费精品 | 极品国产91在线网站 | av在线免费网 | 欧美日韩在线免费观看 | 今井夏帆av一区二区 | 国产精品久久久久久久久久久天堂 | 蜜桃一本色道久久综合亚洲精品冫 | www.99av | 午夜视频大全 | 黄色网欧美 | 欧美三级欧美成人高清www | 护士xxxx| 蜜桃视频在线免费观看 | 亚洲第一页中文字幕 | 国产精品视频六区 |