2009-08-28 118 views
1

#要解決症狀

你怎麼能有效地歸納出以下幾點列?總結兩列了Unix的

列1

1 
3 
3 
... 

列2

2323 
343 
232 
... 

這應該給我

預期結果

2324 
346 
235 
... 

我有兩個文件中的列。


#初始狀態

我有時用太多的大括號這樣的,我已經用我的文件,文件中這個{比這}。 我正在嘗試查找我使用了哪一個不必要的大括號。 我已經使用在獲取數據

發現以下步驟命令

find . * -exec grep '{' {} + > /tmp/1 
find . * -exec grep '}' {} + > /tmp/2 

AWK命令

awk -F: '{ print $2 }' /tmp/1 > /tmp/11 
awk -F: '{ print $2 }' /tmp/2 > /tmp/22 

列在文件的/ tmp/11/tmp目錄/ 22。

我在程序中重複了很多類似的命令。 這表明,這不是正確的方法。

請給我建議任何方式,如Python,Perl或任何可以減少步驟的Unix工具。

+0

謝謝你的回答! - 我接受lutz的回答,因爲他使用了我以前不知道的命令'paste'。 – 2009-08-28 15:27:37

回答

11

如果C1和C2是您選擇的文件,你可以這樣做:

$ paste c1 c2 | awk '{print $1 + $2}' 

或(無AWK):

$ paste c1 c2 | while read i j; do echo $(($i+$j)); done 
11

使用Python:

find . -type f -exec perl -nle 'END { print $ARGV if $h{"{"} != $h{"}"} } $h{$_}++ for /([}{])/g' {}\; 

這需要Perl程序一次:

totals = [ int(i)+int(j) for i, j in zip (open(fname1), open(fname2)) ] 
+0

那就是Python :) – 2009-08-28 14:54:03

+1

在問題中提到了Python,因爲解決方案可以。 – unwind 2009-08-28 14:55:29

+0

你說得對,我跳過了標籤。 – 2009-08-28 14:57:24

3

您可以通過只使用那些計數,並在同一時間進行比較的命令避免中間步驟每個文件,Perl程序計算每個類型大括號的數量,並在文件名稱不匹配時打印該文件的名稱。

您必須注意/([}{]])/部分,find會認爲它需要做{}的替換,如果您說/([{}]])/

警告:如果您試圖針對源代碼運行該代碼,則該代碼將存在誤報和否定。通過使用B::Deparse

while (1) { 
    print "}"; 

可以展開的Perl命令:考慮以下情況:

平衡,但花括號中字符串:

if ($s eq '{') { 
    print "I saw a {\n" 
} 

不平衡,但花括號中字符串

perl -MO = Deparse -nle'END {print $ ARGV if $ h {「{」}!= $ h {「}」}} $ h {$ _} ++ for /([} {])/ g '

導致:

BEGIN { $/ = "\n"; $\ = "\n"; } 
LINE: while (defined($_ = <ARGV>)) { 
    chomp $_; 
    sub END { 
     print $ARGV if $h{'{'} != $h{'}'}; 
    } 
    ; 
    ++$h{$_} foreach (/([}{])/g); 
} 

我們現在可以看看每一塊的程序:

BEGIN { $/ = "\n"; $\ = "\n"; } 

這是由-l選項引起的。它將輸入和輸出記錄分隔符都設置爲「\ n」。這意味着讀入的內容將被分解爲基於「\ n」的記錄,並且任何打印語句都將附加「\ n」。

LINE: while (defined($_ = <ARGV>)) { 
} 

這是由-n選項創建的。它遍歷每一個通過命令行傳入的文件(或STDIN,如果沒有文件通過)讀取這些文件的每一行。這也恰好設置$ARGV<ARGV>讀取的最後一個文件。

chomp $_; 

這消除了無論是在從剛讀取的行($_)的$/變量,它在這裏沒什麼用處。這是由-l選項造成的。

sub END { 
    print $ARGV if $h{'{'} != $h{'}'}; 
} 

這是一個END塊,這段代碼將在程序結束時運行。如果存儲在與密鑰'{''}'相關聯的%h中的值相等,則它打印$ARGV(上次讀取的文件的名稱,參見上文)。

++$h{$_} foreach (/([}{])/g); 

這需要進一步細分:

/ 
    ( #begin capture 
    [}{] #match any of the '}' or '{' characters 
    ) #end capture 
/gx 

是返回的是字符串中被匹配的「{」和「}」字符列表中的正則表達式。由於沒有指定字符串,$_變量(保存從文件中讀取的最後一行,參見上文)將被匹配。該列表被輸入到foreach聲明中,該聲明然後運行它在列表中每個項目(因此名稱)前的聲明。它還設置了$_(因爲你可以看到$_是Perl中流行的變量)是列表中的項目。

++h{$_} 

此線遞增一個與相關聯的$_(其將是「{」或「}」,見上文)通過一個在$ h值。

1

在Python(或Perl,awk中,& c)您可以合理地做一個單獨的「通行證」 - 我不確定你的意思是「太多的花括號」,但你可以確定每個文件的捲曲使用。例如(除非你不必擔心多GB的文件)使用最花括號中,10個文件:

import heapq 
import os 
import re 

curliest = dict() 

for path, dirs, files in os.walk('.'): 
    for afile in files: 
    fn = os.path.join(path, afile) 
    with open(fn) as f: 
     data = f.read() 
     braces = data.count('{') + data.count('}') 
    curliest[fn] = bracs 

top10 = heapq.nlargest(10, curlies, curliest.get) 
top10.sort(key=curliest.get) 
for fn in top10: 
    print '%6d %s' % (curliest[fn], fn) 
0

回覆Lutz'n答案

我的問題終於被這個commnad解決

paste -d: /tmp/1 /tmp/2 | awk -F: '{ print $1 "\t" $2 - $4 }' 
0

你的問題可以只用1條awk命令來解決......

awk '{getline i<"file1";print i+$0}' file2