Text-Processing

替換具有循環結構的第一列的內容

  • June 7, 2021

我有一個要更改第一列的文件,例如,我有以下文件(在原始文件中,我有多個列,但將以下內容截斷為 2 列,文件末尾可能有空行)。

測試.txt:

0 a
2 b  
3 c 
4 d
5 e

我需要將第一列的內容從 0 -> 2, 2 -> 3 , 3 -> 5 , 4 -> 0, 5 -> 4 更改為我的最終文件,

2 a
3 b
5 c
0 d
4 e

我嘗試使用 awk 如下,

awk '$1=="0"{$1="2"} $1=="2"{$1="3"} $1=="3"{$1="5"} $1=="4"{$1="0"} $1=="5"{$1="4"};1' test.txt

但是由於 awk 不會逐行讀取並更改所需的內容,因此輸出是,

4 a
4 b
4 c
0 d
4 e

任何人都可以幫助我轉換為我需要的東西,python、sed 或 awk,或者歡迎任何腳本工具。

AWK實際上是逐行讀取的,你只需要next在列印後為每個賦值添加語句,因此將跳過其餘程式碼。

awk '$1=="0"{ $1="2"; print; next }
    $1=="2"{ $1="3"; print; next }
    $1=="3"{ $1="5"; print; next }
    $1=="4"{ $1="0"; print; next }
    $1=="5"{ $1="4"; print; next }1' infile

或者使用控制標誌:

awk '!s && $1=="0"{ $1="2"; s=1 }
    !s && $1=="2"{ $1="3"; s=1 }
    !s && $1=="3"{ $1="5"; s=1 }
    !s && $1=="4"{ $1="0"; s=1 }
    !s && $1=="5"{ $1="4"; s=1 }
                 { print; s=0  }' infile

但您也可以按以下方式完成所有操作:

awk -F'( )' 'BEGIN{ split("2 1 3 5 0 4", map) }
$1!=""{ $1=($1+1 in map)?map[$1+1]:$1 }1' infile

使用split(string, arryName) 函式,我們創建了一個數組map,其索引和值如下所示,基於 FS 進行拆分(預設為空格/製表符)

Index        Value
map[<0>+1] -->   2
map[<1>+1] -->   we choice it 1 so it will be unchanged for <1> --> 1
map[<2>+1] -->   3
map[<3>+1] -->   5
map[<4>+1] -->   0
map[<5>+1] -->   4

<#>角度內的數字是來自第一列的值,並且由於 awk 中數組的索引從 1 而不是 0 開始,所以我們將列值加一,然後從映射數組中獲取相應的值。


作為通用解決方案(但我仍然會使用上述一個,因為幾乎使用者定義的鍵/值是順序的,並且數組索引可以用作鍵,但是)如果不是這樣,你就去吧:

awk -F'( )' 'BEGIN{ len=split("0 2 2 3 3 5 4 0 5 4", map) }
{ for(i=1; i<=len/2; i+=2 ) if($1==map[i]){ $1=map[i+1]; break} }1' infile

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