awk 進行回顯,直到模式匹配後循環成功

awk 進行回顯,直到模式匹配後循環成功

我有一個文件

XYZ 123 S S R O O S F
PQR 456 F S S R O F F
ABC 789 F S R S S F S

現在,在整行中,當我找到“R”&&然後是“O”或“S”時,我想獲取列號並根據列號我需要執行命令,如果為真則顯示 L 而不是 R 和 O或S 如果為false,則用F 代替R,用F 代替O(對於所有連續的O)或 S

現在從「否」欄中我將確定日期,

假設第一行 R 在 5 上,因此日期將是第 3 列,即第二列,

對於第二行日期將是 6-3 即第三行,第三行又是 5-3 即第二行,

所以我將使用變數 date=%m/d(來自第 3 列)/%Y

現在的命令是./bpimagelist -client <column 1> -policy <column 2> -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l,現在如果值為 0 則為 false,如果為 gt 0 則為 true。

XYZ is false
PQR is true
ABC is true

那麼輸出應該是

XYZ 123 S S F F F S F
PQR 456 F S S L O F F
ABC 789 F S L S S F S

根據 Valentin 的說法,在做了一些修改後,這段程式碼似乎運作得很好。

while read line;
do
    day="$(echo $line | awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 2; exit} } }')"
    if [[ ${#day} -lt 2 ]]; then day="0${day}"; fi
    month=`date '+%m'`
    year=`date '+%Y'`
    date=`echo $month/$day/$year`
    result=$(sudo /usr/openv/netbackup/bin/admincmd/bpimagelist -client "$(echo $line | awk '{print $1}')" -policy "$(echo $line | awk '{print $2}')" -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l)
    if [[ $result -ne 0 ]];
    then
        echo $line | sed 's/ R / L /'
    else
        echo $line | awk '{
                            afterR=0;
                            for (i=1; i<=NF; i++){
                              if ($i == "R") {
                                $i = "F";
                                afterR=1;
                              }
                              if (afterR == 1 && $i == "O") {
                                $i = "F"
                              }
                            }
                            print $0
                          }'
    fi
done < temp

然而,一個小問題是,只有當 R 後面跟著 O 時,它才應該執行這些更改,直到找到 O 之外的任何內容為止。

這意味著如果輸入檔是這樣的,它不應該執行任何更改

XYZ 123 S S R O O O O

這意味著 R 僅由 O 延續,因此無需執行任何更改,否則發現除 O 之外的任何內容都執行更改

答案1

我會盡力一步步回答您的請求。假設這裡input是輸入檔的一行:

擷取第一個「R」字元的列號

對於以下人員來說,這是一項非常簡單的工作awk

 awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 3; exit} } }' < input

考慮到您如何計算日期,我假設“R”不能位於第一行(否則天數可能為 0)。

提取第一列和第二列的值

這更簡單:

awk '{print $1}' < input    # for first column
awk '{print $2}' < input    # for second column

建構輸出

如果命令返回True

sed 's/ R / L /' < input

如果命令返回False

awk '{
       afterR=0;
       for (i=1; i<=NF; i++){
         if ($i == "R") {
           $i = "F";
           afterR=1;
         }
         if (afterR == 1 && $i == "O") {
           $i = "F"
         }
       }
       print $0
     }' < input

把它們放在一起

儘管這是不受歡迎的,但我認為沒有辦法避免循環輸入行,因為您需要為每一行運行一個非常特定的命令。請注意,對於大文件,這可能會非常慢。包含所有這些元素的腳本會是什麼樣子:

while read line;
do
    date="%m/d$(echo $line | awk '{for (i=1; i<=NF; i++) { if($i == "R") { print i - 3; exit} } }')/%Y"
    result=$(./bpimagelist -client "$(echo $line | awk '{print $1}')" -policy "$(echo $line | awk '{print $2}')" -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l)
    if [[ $result -ne 0 ]];
    then
        echo $line | sed 's/ R / L /'
    else
        echo $line | awk '{
                            afterR=0;
                            for (i=1; i<=NF; i++){
                              if ($i == "R") {
                                $i = "F";
                                afterR=1;
                              }
                              if (afterR == 1 && $i == "O") {
                                $i = "F"
                              }
                            }
                            print $0
                          }'
    fi
done < myinputfile.txt

相關內容