2014-01-23 76 views
1

我有這個問題,我需要在同一個文件的同一時間打印2行,問題是它必須發生在第一列的行更改之後,例如:同時打印兩行

文件:abcd.csv

a,1 
a,2 
a,3 
a,4 
a,5 
a,6 
b,1 
b,2 
b,3 
b,4 
b,5 
b,6 
c,1 
c,2 
c,3 
c,4 
c,5 
c,6 

代碼:

awk '{ if ($1 == "a") print $1,$2 } ' FS="," abcd.csv 

它打印:

a 1 
a 2 
a 3 
a 4 
a 5 
a 6 

,但我需要兩條線路在同一時間,因爲我需要管這兩行額外的呼叫:

1輸出(那麼他們將被髮送):

a 1 
a 2 

第2個輸出(然後,他們將被髮送):

a 2 
a 3 

第三輸出(那麼他們將被髮送):

a 3 
a 4 

4個輸出(那麼他們將被髮送):

a 4 
a 5 

5個輸出(那麼他們將被髮送):

a 5 
a 6 

等在第一列中的其他字母。

我會很感激有這方面的提示,

+0

這是否必須在'awk'? – FuriousGeorge

+0

你需要加倍每個轉換線?當第二個字段在兩行「a 1'' a 2'' a 2'' a 3'之間不發生變化時會發生什麼? –

+0

所以你想每次調用你的awk時,你有兩行,第一行,第1,2行,然後是3,4 ...也就是說,如果你調用100次,你解析文件100次...我建議你grep/awk ...來獲得你需要的所有行,然後處理這個較小的集合,並循環。 – Kent

回答

1

我會用getline()功能的無限循環中,並打破它,當第一場是a性格不同:

awk ' 
    FNR == 1 { 
     while (1) { 
      prev_line = $0 
      r = getline 
      if (r != 1) { 
       exit r 
      } 
      split(prev_line, arr_prev, /,/) 
      split($0, arr, /,/) 
      if (arr_prev[1] == "a" && arr[1] == "a") { 
       printf "%s\n%s\n", prev_line, $0 
      } 
      else { 
       exit 0 
      } 
      print "=============" 
     } 
    } 
' infile 

它產生:

a,1 
a,2 
============= 
a,2 
a,3 
============= 
a,3 
a,4 
============= 
a,4 
a,5 
============= 
a,5 
a,6 
============= 

UPDATE:爲避免無限循環,我在getline()結果中添加了一個檢查,以退出文件結尾或發生錯誤。

+0

非常感謝,我根據自己的需求調整了您的答案 – Gery

+2

此解決方案在某些情況下會產生真正的無限循環。如果您正在考慮使用getline,請確保您閱讀http://awk.info/?tip/getline並充分理解所有含義和注意事項。對於getline解決方案來說,這似乎不是一個合適的問題。 –

+0

@EdMorton:是的。我已經更新了腳本來修復它。 – Birei

1

它是從你的問題您可以通過「兩條線在同一時間」,但下面的代碼將在兩個組輸出的每個字母的意思不清楚:

#!/usr/bin/awk -f 

BEGIN { FS=","; OFS=","} 
{ 
    count[$1]++; 
    rows[$1][count[$1]] = $2; 
} 
END { 
    for(i in count) { 
     for(k=1; k<=count[i]-1; k++) { 
      print i,rows[i][k] 
      print i,rows[i][k+1] 
      print "" 
     } 
     print "" 
      print "" 
     } 
    } 

這個代碼設定輸入輸出字段分隔符爲逗號。然後它會創建一個2D哈希,其中第一個字母和該字母組中的行作爲鍵,第二列作爲值。

最後,它會對每個首字母進行二維哈希處理,並在該字母集內以組的兩個組進行打印。您給定的輸入

輸出基地:

a,1 
a,2 

a,2 
a,3 

a,3 
a,4 

a,4 
a,5 

a,5 
a,6 



b,1 
b,2 

b,2 
b,3 

b,3 
b,4 

b,4 
b,5 

b,5 
b,6 



c,1 
c,2 

c,2 
c,3 

c,3 
c,4 

c,4 
c,5 

c,5 
c,6 
+0

你的解決方案真的很好,謝謝你的建議 – Gery

1

如果您不需要使用awk那麼簡單python程序就足夠了:

#!/usr/bin/python 

import sys 

with open(sys.argv[1], 'r') as f: 
    content = f.readlines() 

for i in range(len(content)-1): 
    if content[i].split(',')[0] == content[i+1].split(',')[0]: 
     print content[i] 
     print content[i+1] 
+0

謝謝! – Gery

1

你說你要管每兩個如果你一次性產生所有輸出,那麼你仍然需要分割每一對線路才能進行其他呼叫。

我只是做在bash下面,

FILE=abcd.csv; \ 
    LINES=`wc -l $FILE | cut -d' ' -f1`; \ 
    for N in `seq 2 ${LINES}`; do \ 
     head -n${N} $FILE | tail -n2 | awk '{print $1,$2}' FS="," | cat; \ 
    done 

done與你真正想要撥打電話前更換的最後| cat,這將獲得每對線。

+0

非常感謝安德魯爲您的代碼,簡單而酷的 – Gery

3

你需要你的awk電話後管理此:

awk -F, '$1 == "a" {print $1,$2}' abcd.csv | 
while read line1; do 
    read line2 
    printf "%s\n%s\n" "$line1" "$line2" | additional_call 
done 
+0

偉大的答案,謝謝你的支持 – Gery