中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

Shell腳本實現亂序排列文件內容的多種方法(洗牌問題)
來源:易賢網 閱讀:1295 次 日期:2015-01-30 14:12:40
溫馨提示:易賢網小編為您整理了“Shell腳本實現亂序排列文件內容的多種方法(洗牌問題)”,方便廣大網友查閱!

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

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()

更多信息請查看IT技術專欄

更多信息請查看腳本欄目
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!

2026國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
云南網警備案專用圖標
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
云南網警報警專用圖標
主站蜘蛛池模板: 洪江市| 平谷区| 和林格尔县| 阳谷县| 东阿县| 水富县| 天门市| 金寨县| 集贤县| 司法| 翁源县| 昭平县| 吴忠市| 增城市| 历史| 军事| 塔河县| 芜湖县| 洛隆县| 镇安县| 蓬溪县| 武冈市| 莱阳市| 汕头市| 绥中县| 玛曲县| 玉林市| 苏尼特右旗| 固始县| 南靖县| 平泉县| 泾阳县| 固镇县| 皮山县| 莲花县| 潮安县| 敖汉旗| 广灵县| 加查县| 齐河县| 晋江市|