您好,登錄后才能下訂單哦!
本篇內容主要講解“有哪些用Shell腳本實現亂序排列文件內容的方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“有哪些用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()
到此,相信大家對“有哪些用Shell腳本實現亂序排列文件內容的方法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。