我運行一個測驗環境,我用lorem alg創建了40 000個測驗檔案,這些檔案的大小在20萬到5 MB之間。我想修改很多隨機的檔案。我將通過洗掉2行和插入1行base64字串來改變5%的行。
問題是,這個程式對每個檔案都需要很多時間。我試圖通過將測驗檔案復制到RAM并在那里進行修改來解決,但我看到一個單執行緒只使用了一個完整的核心,并且gawk顯示了最多的cpu作業。我正在尋找一些解決方案,但我沒有找到正確的建議。我認為gawk可以在一個步驟中完成,但對于大檔案,當我用 "getconf ARG_MAX "計算時,我得到一個長字串。
我怎樣才能加快這個速度呢?
zeilen=$(wc -l < testfile$filecount.txt) 。
durchlauf=$(($zeilen/20)
zeilen=$((zeilen-2)
for ( ( c=1; c<=durchlauf; c ))
do
zeile=$(shuf -i 1-$zeilen -n 1) 。
zeile2=$((zeile 1)
zeile3=$((zeile2 1)
string=$(base64 /dev/urandom | tr -dc '[[:print:]' | head -c 230)
if [[ $c -eq 1 ]
then
gawk -v n1="$zeile"/span> -v n2="$zeile2"/span> -v n3="$zeile3" -v s="$string" 'NR==n1{next; 列印}
NR==n2{next; print}。NR==n3{print s}1' testfile$filecount.txt > /mnt/RAM/tempfile.tmp
else
gawk -i inplace -v n1="$zeile"/span> -v n2="$zeile2"/span> - v n3="$zeile3" -v s="$string" 'NR==n1{next; 列印}
NR==n2{next; print}。NR==n3{print s}1' /mnt/RAM/tempfile.tmp
fi
done
uj5u.com熱心網友回復:
我不知道你的腳本的其余部分在做什么,但下面會給你一個想法,如何極大地提高它的性能。
而不是在回圈的每個迭代中呼叫 base64, tr, head, 和 awk,這意味著所有的開銷。
for (( c=1; c<=3; c )
do
string=$(base64 /dev/urandom | tr -dc '[[:print:]' | head -c 230)
echo "$string"| awk '{print "<" $0 ">"}'
done
< nSxzxmRQc11 fFnG7ET4EBIBUwoflPo9Mop0j50C1MtRoLNjb43aNTMNRSMePTnGub5gqDWeV4yEyCVYC2s519JL5OLpBFxSS/xOjbL4pkmoFqOceX3DTmsZrl/RG YLXxiLBjL//I220MQAzpQE5bpfQiQB6BvRw64HbhtVzHYMODbQU1UYLeM6IMXdzPgsQyghv1MCFvs0Nl4Mez2Zh98f9 472c6K 44nmi>。
< 9xfgBc1Y7P/QJkB6PCIfNg0b7V KmSUS49uU7XdT yiBqjTLcNaETpMhpMSt3MLs9GFDCQs9TWKx7yXgbNch1p849IQrjhtZCa0H5rtCXJbbngc3oF9LYY8WT72RPiV/gk4wJrAKYq8/lKYzu0Hms0lHaOmd4qcz1hpzubP7NuiBjv16A8T3slVG1p4vwxa5JyfgIYo4rno219ba/vRMB1QF9HaAppdRMP32>。
< K5kNgv9EN1a/c/7eatrivNeUzKYolCrz5tHE2yZ6XNm1aT4ZZq3OaY5UgnwF8ePIpMKVw5LZNstVwFdVaNvtL6JreCkcO QtebsCYg5sAwIdozwXFs4F4hZ/ygoz3DEeMWYgFTcgFnfoCV2Rct2bg/mAcJBZ9 4x9IS JNTA64T1Zl FJiCuHS05sFIsZYBCqRADp2iL3xcTr913dNplqUvBEEsW1qCk/TDwQh>
你應該這樣寫,每個工具只呼叫一次,所以運行速度會快很多:
你應該這樣寫,每個工具只呼叫一次。
$ base64 /dev/urandom | tr -dc '[[:print:]] ' |
gawk -v RS='.{230}' '{print "<" RT ">"} NR==3{exit}'。NR==3{exit}'
< X0If1qkQItVLDOmh2BFYyswBgKFZvEwyA WglyU0BhqWHLzURt/AIRgL3olCWZebktfwBU6sK7N3nwK6QV2g5VheXIY7qPzkzKUYJXWvgGcrIoyd9tLUjkM3eusuTTp4TwNY6E/z7lT0/2oQrLH/yZr2hgAm8IXDVgWNkICw81BRPUqITNt3VqmYt/HKnL4d/i88F4QDE0XgivHzWAk6OLowtmWAiT8k1a0Me6>。
< TqCyRXj31xsFcZS87vbA50rYKq4cvIIn1oCtN6PJcIsSUSjG8hIhfP8zwhzi6iC33HfL96JfLIBcLrojOIkd7WGGXcHsn0F0XVauOR t8SRqv /t9ggDuVsn6MsY2R4J mppTMB3fcC5787u0dO5vO1UTFWZG0ZCzxvX/3oxbExXb8M54WL6PZQsNrVnKtkvllAT/s4mKsQ/ojXNB0CTw7L6AvB9HU7W2x U3j>
< ESsGZlHjX/nslhJD5kJGsFvdMp PC5KA xOYlcTbc/t9aXoHhAJuy/KdjoGq6VkP v4eQ5lNURdyxs jMHqLVVtGwFYSlc61MgCt0IefpgpU2e2werIQAsrDKKT1DWTfbH1qaesTy2IhTKcEFlW/bc 1en8912Dig7Nn2MD8VQrGn6BzvgjzeGRqGLAtWJWkzQjfx 74ffJQUXW4uuEXA8lBvbuJ8 yQA2WHK5>
uj5u.com熱心網友回復:
@mark-fuso, 哇,真是快得令人難以置信! 但在腳本中存在一個錯誤。檔案的大小增長了一點,這是我必須要避免的事情。我認為,如果兩個隨機的行號($durchlauf)彼此相隨,那么有一行就不會被洗掉。說實話,我并不完全理解你的命令在做什么,但它作業得非常好。我想對于這樣的任務,我必須要有更多的bash經驗。
輸出示例:
64
65
66
gOf0Vvb9OyXY1Tjb1r4jkDWC4VIBpQAYnSY7KkT1gl5MfnkCMzUmN798pkgEVAlRgV9GXpknme46yZURCaAjeg6G5f1Fc7nc7AquIGnEER>。
AFwB9cnHu6SRnsupYCPViTC9XK fwGkiHvEXrtw2aosTGAAFyu0GI8Ri2 NoJAvMw4mv/FE72t/xapmG5wjKpQYsBXYyZ9YVV0SE6c6rL>
70
71
uj5u.com熱心網友回復:
假設:
- 生成
$durchlauf(一個數字)的隨機行號;我們將單個數字稱為n... - 從輸入檔案中洗掉編號為
n和n 1的行,并在其位置上 ... - 插入
$string(一個隨機生成的base64字串) - 這個隨機行號的串列不能有任何連續的行號 。
正如其他人所指出的,你想限制自己在每個輸入檔案中只呼叫一次gawk。
新方法:
- 生成
$durchlauf(計數)亂數(見gen_numbers()函式) - 生成
$durchlauf(count)base64字串(我們將重新使用 Ed Morton 的代碼) 。
paste這2組資料到一個單一的輸入流/檔案 。
- 向
gawk提供2個檔案...paste結果和要修改的實際檔案 。
- 我們不能使用
gawk的-i inplace,所以我們將使用一個中間的臨時檔案 。
- 當我們在輸入檔案中找到一個匹配的行時,我們將1)插入
base64字串,然后2)跳過/洗掉當前/下一個輸入行;這應該可以解決我們有兩個亂數字不同的問題1。
一個確保我們不產生連續行數的想法:
- 將我們的行號集合分成范圍,例如,100行分成5個范圍=>
1-20/21-40/41-60/61-80/81-100<
- 將每個范圍的末端減少1,例如,
1-19/21-39/41-59/61-79/81-99 - 使用
$RANDOM來生成每個范圍之間的數字(這往往比類似的shuf呼叫至少快一個數量級)
我們將使用一個函式來生成我們的非連續行號串列:
gen_numbers ( ) {
max=$1 # $zeilen eg, 100
count=$2 # $durchlauf eg, 5
interval=$( ( ( max / count )) # eg, 100 / 5 = 20
for ( ( ( start=1; start<max; start=start interval ))
do
end=$( ( ( start interval - 2 ))
out=$( ( ( RANDOM % interval ) start ))
[[ $out -gt $end ]] && out=${end}。
echo ${out}
done
}
示例運行:
$ zeilen=100
$ durchlauf=5
$ gen_numbers ${zeilen} ${durchlauf}
17
31
54
64
86
演示一下paste/gen_numbers/base64/tr/gawk的想法:
$ zeilen=300
$ durchlauf=3
$ paste <( gen_numbers ${zeilen} ${durchlauf} ) <( base64 /dev/urandom | tr -dc ' [[: print:]] ' | gawk -v max="${durchlauf}" -v RS=' 。 {230}' '{print RT}. FNR==max{exit}' )
這就產生了:
74 7VFhnDN4J...snip...rwnofLv
142 ZYv07oKMB...snip...xhVynvw
261 gifbwFCXY...狙擊...hWYio3e
主代碼:
tmpfile=$(mktemp)
while/for回圈 ... # whatever OP is using to loop over list of input files.
do
zeilen=$(wc -l < "testfile${filecount}"/span>.txt)
durchlauf=$( ( ( $zeilen/20 ) )
awk '
# 處理第一個檔案(即粘貼/gen_numbers/base64/tr/gawk)
FNR==NR { ins[1]=$2 # 將base64存盤在ins[]陣列中
del[1]=del[(1) 1] # 記下 zeilen 和 zeilen 1 的行號以便洗掉
下一個
}
# 處理第二個檔案
ins中的FNR { print ins[FNR] } # 插入base64字串?
! (FNR in del) # 如果當前行號不在del[]陣列中,則列印該行
' <( paste <( gen_numbers ${zeilen} ${durchlauf} ) <( base64 /dev/urandom | tr -dc ' [: print:]] ' | gawk -v max="${durchlauf}" -v RS=' 。 {230}' '{print RT}. FNR==max{exit}' )) "testfile${filecount}".txt > "${tmpfile}"。
# 最后一行,為了便于閱讀,要有續行:
#' < (paste
# <( gen_numbers ${zeilen} ${durchlauf} )
# <( base64 /dev/urandom | tr -dc '[[:print:]]' | gawk -v max="${durchlauf}" -v RS='.{230}' '{print RT}. FNR==max{exit}' )
# )
#"testfile${filecount}".txt > "${tmpfile}"
mv "${tmpfile}"/span> "testfile${filecount}"/span>.txt
done。
awk代碼操作的簡單例子:
$ cat orig.txt
line1
line2
line3
line4
line5
第6行
第7行
第8行
第9行
$ cat paste.out # simulated output from paste/gen_numbers/base64/tr/gawk
1 newline1
5 newline5
$ awk '...'/span> paste.out orig.txt
新行1
第3行
第4行
新行5
第7行
第8行
第9行
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/324951.html
標籤:
上一篇:巴什當地可變范圍的最佳做法
