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

相关内容