Awk

替換列中的模式

  • February 12, 2020

我需要將來自不同文件的文件中的模式替換為輸入。

讓我們說 file1 內容:

ab 10
bc 20
cd 30
de 40

文件2:

server1;10 feb 2020;disk5;123455678;comment;10;1;desc;abcde3;987654
server1;10 feb 2020;disk6;123455678;comment;10;7;desc;abcde3;987654
server1;10 feb 2020;disk10;123455678;comment;20;4;desc;abcde3;987654
server1;10 feb 2020;disk1;123455678;comment;30;5;desc;abcde3;987654
server1;10 feb 2020;disk9;123455678;comment;20;4;desc;abcde3;987654
server1;10 feb 2020;disk2;123455678;comment;40;6;desc;abcde3;987654
server1;10 feb 2020;disk5;123455678;comment;30;8;desc;abcde3;987654

在這裡,作為;file2 中的分隔符,我想用 file1 中的匹配值替換第 6 列。

IE

server1;10 feb 2020;disk5;123455678;comment;**ab**;1;desc;abcde3;987654

我知道它可能通過awk/ sed。你能幫忙嗎?注意:我們不使用 GNU 版本的awk/sed作為它的AIX.

本練習的難點在於如何在同一個awk程序中處理不同的欄位分隔符。

使用 GNU awk

$ gawk 'FNR == NR { pat[$2] = $1; next } ($6 in pat) { $6 = pat[$6] } { print } ENDFILE { OFS = FS = ";" }' file1 file2
server1;10 feb 2020;disk5;123455678;comment;ab;1;desc;abcde3;987654
server1;10 feb 2020;disk6;123455678;comment;ab;7;desc;abcde3;987654
server1;10 feb 2020;disk10;123455678;comment;bc;4;desc;abcde3;987654
server1;10 feb 2020;disk1;123455678;comment;cd;5;desc;abcde3;987654
server1;10 feb 2020;disk9;123455678;comment;bc;4;desc;abcde3;987654
server1;10 feb 2020;disk2;123455678;comment;de;6;desc;abcde3;987654
server1;10 feb 2020;disk5;123455678;comment;cd;8;desc;abcde3;987654

在這裡,我們開始讀取第一個文件,在關聯數組中填充pat我們希望稍後在第 6 列中替換的內容。鍵是我們替換的東西,值是我們替換它們的東西。

當 GNUawk讀完一個文件時,它會執行該ENDFILE塊,如果它存在的話(還有一個BEGINFILE塊在某些情況下可能有用)。 ENDFILE並且BEGINFILE就像“本地文件”BEGINEND塊。

在這裡,我們使用ENDFILE將輸入和輸出欄位分隔符更改為分號。

在讀取第二個文件時,我們只是測試第 6 個欄位中的數據是否可用作鍵pat,如果是,我們將其值替換為該鍵的值。列印第二個文件中的所有行,無論是否修改。

使用非 GNU awk,可以這樣做:

$ awk 'FNR == NR { pat[$2] = $1; next } { OFS = FS = ";"; $0=$0 } ($6 in pat) { $6 = pat[$6] } { print }' file1 file2
server1;10 feb 2020;disk5;123455678;comment;ab;1;desc;abcde3;987654
server1;10 feb 2020;disk6;123455678;comment;ab;7;desc;abcde3;987654
server1;10 feb 2020;disk10;123455678;comment;bc;4;desc;abcde3;987654
server1;10 feb 2020;disk1;123455678;comment;cd;5;desc;abcde3;987654
server1;10 feb 2020;disk9;123455678;comment;bc;4;desc;abcde3;987654
server1;10 feb 2020;disk2;123455678;comment;de;6;desc;abcde3;987654
server1;10 feb 2020;disk5;123455678;comment;cd;8;desc;abcde3;987654

這有點低效,但它的作用是對於第二個文件中的每一行,它設置OFSFS重新;拆分輸入。

一個稍微更有效(但仍然醜陋)的變體是只為第二個文件中的第一行設置OFS和:FS

awk 'FNR == NR { pat[$2] = $1; next } FS != ";" { OFS = FS = ";"; $0=$0 } ($6 in pat) { $6 = pat[$6] } { print }' file1 file2

假設所有 $6 值都包含在 file1 中,請嘗試

awk 'FNR == NR {T[$2] = $1; next} {$6 = T[$6]} 1' file1 FS=";" OFS=";" file2

引用自:https://unix.stackexchange.com/questions/567153