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」を見つけたら、列番号を取得し、その列番号に基づいてコマンドを実行し、trueの場合は代わりにLを表示する必要があります。 RとOまたはSが偽の場合は、RをFに置き換え、OをF(すべての連続Oに対して)またはSに置き換えます。

「いいえ」列で日付を決定します。

最初の行Rが5にあると仮定すると、日付は2番目の列である3列になります。

2行目の場合、日付は6-3、つまり3行目になり、3行目の場合、日付は5-3、つまり2行目になります。

したがって、変数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

しかし、1つの小さな問題は、Rの後にOが来る場合にのみ、O以外のものが見つかるまでこれらの変更を行う必要があることです。

これは、入力ファイルが次のような場合、いかなる変更も行わないでください。

XYZ 123 S S R O O O O

これは、RがOによってのみ続くため、変更を行う必要がなく、そうでなければO以外の項目が見つかった場合に変更が行われることを意味します。

ベストアンサー1

お客様のご要望に段階的にお答えいたします。以下がinput入力ファイルの1行であるとします。

最初の「R」文字の列番号を抽出します。

これは非常に簡単な作業ですawk

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

日付の計算方法を考えると、「R」は最初の行には存在できないと仮定します(そうしないと、日数はゼロになる可能性があります)。

最初と2番目の列の値を抽出します。

これはもっと簡単です:

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

おすすめ記事