awk zum Echo, bis die If-Schleife nach der Musterübereinstimmung erfolgreich ist

awk zum Echo, bis die If-Schleife nach der Musterübereinstimmung erfolgreich ist

Ich habe eine Datei

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

Wenn ich jetzt in der gesamten Zeile "R" und dann "O" oder "S" finde, möchte ich die Spaltennummer erhalten und basierend auf der Spaltennummer muss ich einen Befehl ausführen und wenn dieser wahr ist, dann L statt R und O oder S anzeigen, wenn er falsch ist, dann F statt R und F statt O (für alle aufeinanderfolgenden O's) oder S

jetzt ermittle ich aus der Spalte Nr. das Datum,

sagen wir für die 1. Zeile R ist am 5, also wird das Datum in Spalte Nr. - 3 sein, also am 2.,

für die 2. Reihe ist das Datum 6-3, also 3., 3. Reihe wieder 5-3, also 2.,

Daher verwende ich die Variable date=%m/d(aus Spalte Nr. 3)/%Y

jetzt ist der Befehl ./bpimagelist -client <column 1> -policy <column 2> -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l, wenn der Wert 0 ist, dann ist er falsch, wenn er 0 ist, dann ist er wahr.

XYZ is false
PQR is true
ABC is true

dann sollte die Ausgabe sein

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

Laut Valentin scheint dieser Code nach einigen Änderungen einwandfrei zu funktionieren.

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

Eine kleine Abfrage besteht jedoch darin, dass diese Änderungen nur durchgeführt werden sollen, wenn auf R O folgt und bis etwas anderes als O gefunden wird.

Das heißt, es sollten keine Änderungen vorgenommen werden, wenn die Eingabedatei wie folgt aussieht:

XYZ 123 S S R O O O O

Das bedeutet, dass R nur durch O fortgesetzt wird, sodass keine Änderungen vorgenommen werden müssen. Andernfalls werden die Änderungen vorgenommen, wenn etwas anderes als O gefunden wird.

Antwort1

Ich werde versuchen, Ihre Anfrage Schritt für Schritt zu beantworten. Nehmen Sie hier einfach an, dass dies inputeine Zeile Ihrer Eingabedatei ist:

Extrahieren der Spaltennummer des ersten "R"-Zeichens

Dies ist eine ziemlich einfache Aufgabe für awk:

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

Angesichts der Art und Weise, wie Sie Ihr Datum berechnen, gehe ich davon aus, dass das „R“ nicht in der ersten Zeile stehen kann (sonst könnte die Tagesnummer 0 sein).

Extrahieren von Werten der 1. und 2. Spalte

Das geht noch einfacher:

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

Ausgabe erstellen

Falls der Befehl zurückgibt True:

sed 's/ R / L /' < input

Falls der Befehl zurückgibt 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

Alles zusammenfügen

Obwohl dies verpönt ist, sehe ich keine Möglichkeit, die Schleife über Ihre Eingabezeilen zu vermeiden, da Sie für jede Zeile einen ganz bestimmten Befehl ausführen müssen. Beachten Sie, dass dies bei großen Dateien sehr langsam sein kann. So könnte Ihr Skript mit all diesen Elementen aussehen:

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

verwandte Informationen