2014-06-27 73 views
1

想提取所有從第一個文件中的行(gunzip解*。廣州即Input.csv.gz),如果第一個文件第四場是落在範圍 第二個文件內( Slab.csv)第一個字段(Start Range)和第二個字段(End Range),然後填充第一個文件的第四和第五個字段的行數和總數。awk的數量和金額:

Input.csv.gz(gunzip解)

Desc,Date,Zone,Duration,Calls 
AB,01-06-2014,XYZ,450,3 
AB,01-06-2014,XYZ,642,3 
AB,01-06-2014,XYZ,0,0 
AB,01-06-2014,XYZ,205,3 
AB,01-06-2014,XYZ,98,1 
AB,01-06-2014,XYZ,455,1 
AB,01-06-2014,XYZ,120,1 
AB,01-06-2014,XYZ,0,0 
AB,01-06-2014,XYZ,193,1 
AB,01-06-2014,XYZ,0,0 
AB,01-06-2014,XYZ,161,2 

Slab.csv

StartRange,EndRange 
0,0 
1,10 
11,100 
101,200 
201,300 
301,400 
401,500 
501,10000 

預期輸出:

StartRange,EndRange,Count,Sum-4,Sum-5 
0,0,3,0,0 
1,10,NotFound,NotFound,NotFound 
11,100,1,98,1 
101,200,3,474,4 
201,300,1,205,3 
301,400,NotFound,NotFound,NotFound 
401,500,2,905,4 
501,10000,1,642,3 

我使用下面兩個命令來得到上面的輸出,期待「NotFound」的情況。

awk -F, 'NR==FNR{s[NR]=$1;e[NR]=$2;c[NR]=$0;n++;next} {for(i=1;i<=n;i++) if($4>=s[i]&&$4<=e[i]) {print $0,","c[i];break}}' Slab.csv <(gzip -dc Input.csv.gz) >Op_step1.csv 
cat Op_step1.csv | awk -F, '{key=$6","$7;++a[key];b[key]=b[key]+$4;c[key]=c[key]+$5} END{for(i in a)print i","a[i]","b[i]","c[i]}' >Op_step2.csv 

Op_step2.csv

101,200,3,474,4 
501,10000,1,642,3 
0,0,3,0,0 
401,500,2,905,4 
11,100,1,98,1 
201,300,1,205,3 

任何建議,以使一個襯命令來實現預期的輸出,不要有Perl,Python的訪問。

回答

2

下面是使用awksort一個辦法:

awk ' 
BEGIN { 
    FS = OFS = SUBSEP = ","; 
    print "StartRange,EndRange,Count,Sum-4,Sum-5" 
} 
FNR == 1 { next } 
NR == FNR { 
    ranges[$1,$2]++; 
    next 
} 
{ 
    for (range in ranges) { 
     split(range, tmp, SUBSEP); 
     if ($4 >= tmp[1] && $4 <= tmp[2]) { 
      count[range]++; 
      sum4[range]+=$4; 
      sum5[range]+=$5; 
      next 
     } 
    } 
} 
END { 
    for(range in ranges) 
     print range, (count[range]?count[range]:"NotFound"), (sum4[range]?sum4[range]:"NotFound"), (sum5[range]?sum5[range]:"NotFound") | "sort -t, -nk1,2" 
}' slab input 
StartRange,EndRange,Count,Sum-4,Sum-5 
0,0,3,NotFound,NotFound 
1,10,NotFound,NotFound,NotFound 
11,100,1,98,1 
101,200,3,474,4 
201,300,1,205,3 
301,400,NotFound,NotFound,NotFound 
401,500,2,905,4 
501,10000,1,642,3 
  • 設置輸入,輸出字段分隔符和SUBSEP,。打印標題行。
  • 如果是第一行則跳過它。
  • 加載到陣列的整個slab.txt稱爲ranges
  • 對於ranges陣列中的每個範圍,分割字段以獲得開始和結束範圍。如果第四列在該範圍內,則遞增計數數組並適當地將該值添加到sum4sum5數組。
  • END塊中,遍歷範圍並打印它們。
  • 將輸出輸出到sort以獲得輸出順序。
+0

非常感謝Japal,它的正常工作! – VNA

3

這是使用perl的另一個選項,它利用創建多維數組和散列的好處。

perl -F, -lane' 
BEGIN { 
    $x = pop; 
    ## Create array of arrays from start and end ranges 
    ## $range = ([0,0] , [1,10] ...) 
    (undef, @range)= map { chomp; [split /,/] } <>; 
    @ARGV = $x; 
} 
## Skip the first line 
next if $. ==1; 
## Create hash of hash 
## $line = '[0,0]' => { "count" => counts , "sum4" => sum_of_col4 , "sum5" => sum_of_col5 } 
for (@range) { 
    if ($F[3] >= $_->[0] && $F[3] <= $_->[1]) { 
    $line{"@$_"}{"count"}++; 
    $line{"@$_"}{"sum4"} +=$F[3]; 
    $line{"@$_"}{"sum5"} +=$F[4]; 
    } 
} 
}{ 
    print "StartRange,EndRange,Count,Sum-4,Sum-5"; 
    print join ",", @$_, 
    $line{"@$_"}{"count"} //"NotFound", 
    $line{"@$_"}{"sum4"} //"NotFound", 
    $line{"@$_"}{"sum5"} //"NotFound" 
    for @range 
' slab input 
StartRange,EndRange,Count,Sum-4,Sum-5 
0,0,3,0,0 
1,10,NotFound,NotFound,NotFound 
11,100,1,98,1 
101,200,3,474,4 
201,300,1,205,3 
301,400,NotFound,NotFound,NotFound 
401,500,2,905,4 
501,10000,1,642,3 
+1

只是一些清潔https://gist.github.com/mpapec/847669e027df33046fac –

+0

非常感謝@mpapec。真棒反饋。在工作中,'// //'似乎不適用於我的古代'perl'(5.8.8)。將在家測試它。非常感謝..讚賞':)'。 –

+1

檢查'plenv',你可以在你的home文件夾中有v5.20或其他任何文件。 https://github.com/tokuhirom/plenv –