Text-Processing

awk - 如果列1我不知道____ualtothepreviouscolumn1一世sn○噸eq你一個l噸○噸Heprev一世○你sC○l你米n1 is not equal to the previous column1 然後列印整個前一…

  • October 23, 2022

我正在嘗試在 Linux 上編寫一個 awk 程序,如果第一列中的字元串與上一行第一列中的字元串不同,它將列印整個上一行。

另一種說法是,每當第一列相等時,列印整個匹配列的最後一行並丟棄前一個相等的列。

我使用了這段程式碼:

awk 'BEGIN { FS=OFS=";" } $1==last{next} {last=$1} {print last}' test.txt

但我想它只是列印前一行的第一列。如何列印整個前一行?

我的輸入文件,test.txt看起來像這樣:

818522;"Joey";
817399;"john";
817399;"CCE";
817399;"smith";
817399;"Ron";
817400;
817400;
817400;
818000;"ODC";
890021;
890021;
890021;"rachel";
890021;"monica"

期望的輸出:

818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"
$ awk -F';' '$1 != l1 && l1 != "" { print l0 };
            {l1 = $1; l0 = $0};
            END {if ($1 != $l1) {print}}' test.txt 
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"

-F';'選項將 awk 的輸入欄位分隔符 ( FS) 設置為分號。awk 自動拆分每個輸入行FS並將欄位分配給 $ 1, $ 2、 $ 3, ….., $ n.

變數l1l0用於保存第一個欄位 ( $1) 和整行 ( $0)。

在大多數情況下,awk腳本是一系列PATTERN { ACTION }規則 - 如果 PATTERN 評估為真,則執行 ACTION。PATTERN 可以是任何評估為真或假的東西(正則表達式匹配、變數比較、計算等)。ACTION 可以是任何 awk 程式碼語句。這些規則對每一行輸入重複。請注意,PATTERN 或 ACTION 都可以是可選的 - 如果缺少 PATTERN,則將其視為評估為 true,並且始終執行 ACTION。如果缺少 ACTION,則預設操作是print(即列印目前輸入行)。這只是一個非常簡短和簡化的摘要,有關更多詳細資訊,請閱讀 awk 文件(例如man awk,或者,如果您使用 GNU awk,.info awk還有 O’Reilly sed & awk戴爾·多爾蒂和阿諾德·羅賓斯的書)。

awk 腳本的第一行測試目前行是否$1等於l1 字元串。如果兩個測試都為真,它會列印最後一個輸入行l0. 在輸入的第一行,l1總是空的(因為腳本的第二行還沒有執行,所以沒有給它賦值),所以什麼都不會列印(l0反正也是空的,所以列印它只會輸出一個空行)。

awk 腳本的第二行無條件地從目前輸入行設置l1和。l0

該腳本為每一行輸入重複這兩行程式碼。

當沒有更多輸入時,主腳本循環結束並END {...}執行該塊。它列印目前輸入行(即輸入的最後一行) - 目前僅當$1 != l1但經過反思(以及一些簡短的測試)時,如果沒有該測試,它可能也可以正常工作,只是END {print}.

您的描述與您的輸出不匹配,所以我有點困惑。根據您的描述,預期的輸出應該是:

818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";

您不會列印任何890021行,因為它們是最後一行,因此它們的第一個欄位永遠不會與下一行不同。如果這確實是你想要的,你可以這樣做:

$ awk -F';' '{ 
               if($1!=last && prevLine){ print prevLine } 
               { last=$1; prevLine=$0 }
            }' file
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";

如果您還想為最後一行添加異常,請嘗試以下操作:

$ awk -F';' '{ 
             if($1!=last && prevLine){
               print prevLine; 
               lastPrinted=last
             } 
             {
               last=$1; 
               prevLine=$0
             }
            }
            END{ 
               if($1 != lastPrinted){ print }
            }' file 
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"

這個想法很簡單:如果第一個欄位不一樣last並且定義了prevLine變數(所以我們不列印第一行),那麼我們列印上一行(prevLine)並保存上一行的第一個欄位(last) 在變數中lastPrinted

然後,對於所有行,我們設置last為第一個欄位和prevLine目前行。最後,當我們到達文件的末尾時END{}lastPrinted

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