2013-08-29 293 views
1

我想編寫一個代碼來輸出一個awk和bash腳本。這個腳本基本上將文件分割成小塊,以便程序並行運行,並且我想控制peices的數量,而不是像現在這樣設置一個數字。我現在的代碼被設置爲使用awk將文件剪切成10個部分,然後執行bash腳本。Awk/Bash寫腳本

awk -v a=$a '{if (NR<(a/10)&&NR>=0) print }' $1 > $11 
awk -v a=$a '{if (NR<(a/10*2)&&NR>=(a/10*1)) print }' $1 >$12 
awk -v a=$a '{if (NR<(a/10*3)&&NR>=(a/10*2)) print }' $1 >$13 
awk -v a=$a '{if (NR<(a/10*4)&&NR>=(a/10*3)) print }' $1 >$14 
awk -v a=$a '{if (NR<(a/10*5)&&NR>=(a/10*4)) print }' $1 >$15 
awk -v a=$a '{if (NR<(a/10*6)&&NR>=(a/10*5)) print }' $1 >$16 
awk -v a=$a '{if (NR<(a/10*7)&&NR>=(a/10*6)) print }' $1 >$17 
awk -v a=$a '{if (NR<(a/10*8)&&NR>=(a/10*7)) print }' $1 >$18 
awk -v a=$a '{if (NR<(a/10*9)&&NR>=(a/10*8)) print }' $1 >$19 
awk -v a=$a '{if (NR<=(a/10*10)&&NR>=(a/10*9)) print }' $1 >$110 

bash $2 $11& 
bash $2 $12& 
bash $2 $13& 
bash $2 $14& 
bash $2 $15& 
bash $2 $16& 
bash $2 $17& 
bash $2 $18& 
bash $2 $19& 
bash $2 $110& 

我想要它,所以我可以鍵入20,它會將此腳本寫出20次。我似乎無法想出一個方法來做到這一點,在我的腦海中循環。

感謝您的幫助。

編輯

變量上更多的一些信息

a=`wc -l $1 | cut -f 1 -d " "` 

我也不清楚如何寫一個循環來給下面的代碼:

cat $11.tab $12.tab $13.tab $14.tab $15.tab $16.tab $17.tab $18.tab $19.tab $110.tab > $3 
+1

你應該看看'split'命令,它可以取代你的awk系列的命令(和將只需要掃描的文件一次)。然後,您可以循環執行'split'生成的一組文件,並啓動並行bash命令。 –

+0

'$ 110'大概是'$ 20'的錯字,應該是'$ {20}'。所有的雙位數位置參數都應該括在大括號中 - [位置參數](http://www.gnu.org/software/bash/manual/bash.html#Positional-Parameters)。如果你的意思是'$ {1} 1','$ {1} 2'等,那麼你應該使用大括號來清除它(或者使用一個點來分隔'$ 1.1'部分,或者...)。 –

+0

'$ a'中的值是多少? 「$ 1」中的行數是多少?正如'a = $(wc -l <​​$ 1)'或therabouts? –

回答

1

這個答案不探索替代方案,如使用splitcsplit來分區文件。

假設a=$(wc -l < $1),並且$3包含碎片的數量(10寫出普通寫法的例子),則可以採取現有的代碼,並使用seq生成所需的數字打包爲一個或兩個環:

a=$(wc -l < "$1") 
n=${3:-10} 
for i in $(seq 1 $n) 
do 
    # a = number of records in file 
    # n = number of parts the file is to be split into 
    # p = part number of current part 
    awk -v a=$a -v n=$n -v p=$i '{if (NR<(a/n*p)&&NR>=(a/n*(p-1))) print }' "$1" >"$1.$i" 
    bash "$2" "$1.$i" & 
done 
wait # For all the background processes to complete 

這是單循環版本;您可以先創建所有文件,然後運行第二個循環來創建所有後臺進程。

我強烈懷疑,你可以使用一個單一的awk腳本分割文件:

a=$(wc -l < "$1") 
n=${3:-10} 
awk -v a=$a -v n=$n -v f="$1" -e \ 
    '{ nfn = int((n*NR)/a)+1; 
     if (nfn != ofn) 
     { 
      ofile = sprintf("%s.%d", f, nfn); 
      ofn = nfn; 
     } 
     print > ofile 
    }' "$1" 

for i in $(seq 1 $3) 
do 
    bash "$2" "$1.$i" & 
done 
wait # For all the background processes to complete 

這段代碼中沒有已經過去awkbash所以有可能是在它的錯誤。

+0

你會介意解釋n =語句,我不明白。 – jeffpkamp

+0

您可以使用'-v var = value'表示法將shell變量作爲'awk'變量傳遞給'awk'。因此,我已經將三個shell變量傳遞給了第二個'awk'腳本:'aw''腳本中的$ a'被稱爲'a','$ n'被稱爲'n',''1 「'被稱爲'f'。我可以使用'-v lines = $ a'來從shell變量'$ a'在'awk'中命名變量'lines';沒有義務在shell和awk中使用相同的名稱(但這樣做通常是有意義的)。 –

+0

抱歉,我的意思是n = $ {3:-10}語句 – jeffpkamp

1

split看起來像一個簡單的選擇:

INPUT=$1 # input file 
N=$2  # number of lines per file 
SCRIPT=$3 # script to run 

mkdir chunks 
cd chunks 
split "../$INPUT" -l "$N" 
for file in *; do 
    bash "../$SCRIPT" "$file" & 
done