2012-12-10 39 views
-1

對應的匹配字符串替換文件1串的標題可能會產生混淆,這裏就是我想要做的事:匹配來自文件1在文件2串並在文件2

File1 
12=921:5,895:5,813:5,853:5,978:5,807:5,1200:5,1067:5,827:5 

File2 
Tom 12 John 921 Mike 813 

Output 
Tom=John:5,Mike:5 

的文件2具有file1中數字的值,我想匹配並用字符串值替換數字。我用awk的有限知識嘗試了這一點,但無法做到這一點。

任何幫助表示讚賞。

+0

@kikumbob我試圖使用分割線file1中的「:」和「=」分隔符,和在匹配文件2,但是不能夠與對應的列替換。 – Kaartz

+0

要分割的','而不是':'。然後,您可以一次循環一組數據。當你循環每一組時,你可以嘗試一個替換。如果替換有效,則顯示輸出。 –

回答

1

下面是使用GNU awk的一種方式。的script.awk

awk -f script.awk file1 file2 

內容:

BEGIN { 
    FS="[ =:,]" 
} 

FNR==NR { 
    a[$1]=$0 
    next 
} 

$2 in a { 
    split(a[$2],b) 
    for (i=3;i<=NF-1;i+=2) { 
     for (j=2;j<=length(b)-1;j+=2) { 
      if ($(i+1) == b[j]) { 
       line = (line ? line "," : "") $i ":" b[j+1] 
      } 
     } 
    } 
    print $1 "=" line 
    line = "" 
} 

結果:像運行

Tom=John:5,Mike:5 

另外,這裏是一個班輪:

awk -F "[ =:,]" 'FNR==NR { a[$1]=$0; next } $2 in a { split(a[$2],b); for (i=3;i<=NF-1;i+=2) for (j=2;j<=length(b)-1;j+=2) if ($(i+1) == b[j]) line = (line ? line "," : "") $i ":" b[j+1]; print $1 "=" line; line = "" }' file1 file2 

說明:

將awk的字段分隔符更改爲空格,等號,冒號或逗號。

'FNR == NR {...}'僅適用於參數列表中的第一個文件。

因此,在處理file1時,awk會將列'1'添加到數組中,並將整行作爲值分配給此數組元素。

'next'將簡單地跳過處理腳本的其餘部分,並讀取下一行輸入。

當awk讀完file1中的輸入時,它將繼續讀取file2。但是,這也會將'FNR'重置爲'1',所以awk將跳過處理file2的'FNR == NR'塊,因爲它不再是真的。

所以對於file2的:

拆分數組元素到另一個數組的值:如果列「2」可被如上所述在陣列中找到。這基本上分開了file1中的整個行。

現在創建兩個循環。

通過所有名字的第一個將循環file2中

並通過(第二)陣列中的所有的值的第二個將環(這基本上循環遍歷所有字段file1中)。

現在,當file2中成功的一個名字值在文件1等於關鍵數字的一個,創建一個線結構,看起來像:「名稱:number_following_key_number_from_file1」。

當循環過程中發現更名稱和值,季構建體「(......:?...)」添加這些元素到行的結尾。這就像一個if語句;如果已經有一行,請在其末尾添加逗號,否則不要執行任何操作。

當所有的循環完成後,打印出列「1」而行。然後清空行變量,以便可以再次使用它。

HTH。祝你好運。

+0

非常感謝史蒂夫。如果你能解釋我的代碼,這將是非常好的。 – Kaartz

+0

@Kaartz:沒問題。我添加了一些解釋。如果有,我還沒有覆蓋的概念,請讓我知道,我可以嘗試,並解釋多一些。 HTH。 – Steve

+0

非常感謝您的解釋。 – Kaartz

0

下可能工作爲模板:

[email protected] ~/ perl -e '$values="12=921:5,895:5,813:5,853:5,978:5,807:5,1200:5,1067:5,827:5"; 
$data = "Tom 12 John 921 Mike 813"; 
($line,$values)=split/=/,$values; 
@values=split/,/,$values; 
$values{$line}="="; 
map{$_=~/(\d+)(:\d+)/;$values{$1}="$2";}@values; 
if ($data=~/\w+\s$line\s/){ 
    $data=~s/(\w+)\s(\d+)\s?/$1$values{$2}/g; 
} 
print "$data\n"; 
' 
Tom=John:5Mike:5 
[email protected] ~/