awk para ecoar até que o loop seja bem-sucedido após a correspondência do padrão

awk para ecoar até que o loop seja bem-sucedido após a correspondência do padrão

Eu tenho um arquivo

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

Agora, em toda a linha, quando encontro "R" && e depois "O" ou "S", quero obter a coluna não e com base na coluna não, preciso executar um comando e, se for verdade, exibir L em vez de R e O ou S se for falso então F em vez de R e F em vez de O (para todos os O's consecutivos) ou S

agora a partir da coluna não vou determinar a data,

digamos que para a primeira linha R esteja em 5, então a data será a coluna nº - 3, ou seja, 2ª,

para a data da 2ª linha será 6-3, ou seja, 3ª, 3ª linha novamente 5-3, ou seja, 2ª,

Então, usarei uma variável date=%m/d(da coluna no-3)/%Y

agora o comando é ./bpimagelist -client <column 1> -policy <column 2> -hoursago 100000 -U | awk -v date="$date" '$1 == date' | wc -l, agora se o valor for 0 então é falso se for gt 0 então é verdadeiro.

XYZ is false
PQR is true
ABC is true

então a saída deve ser

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

Segundo Valentin, depois de fazer algumas alterações este é o código que parece funcionar bem.

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

No entanto, uma pequena questão é que ele deve realizar essas alterações somente quando R for seguido por O e até encontrar qualquer coisa que não seja O.

o que significa que não deve realizar nenhuma alteração se o arquivo de entrada for como

XYZ 123 S S R O O O O

o que significa que R é continuado apenas por O, portanto não há necessidade de realizar nenhuma alteração, caso contrário, qualquer coisa diferente de O será encontrada, execute as alterações

Responder1

Tentarei responder passo a passo ao seu pedido. Apenas suponha que aqui inputseja uma linha do seu arquivo de entrada:

Extraindo o número da coluna do primeiro caractere “R”

Este é um trabalho bastante simples para awk:

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

Considerando como você está calculando sua data, presumo que o 'R' não pode estar na primeira linha (caso contrário, o número do dia poderia ser 0).

Extraindo valores da 1ª e 2ª coluna

Isso é ainda mais simples:

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

Construindo saída

Caso o comando retorne True:

sed 's/ R / L /' < input

Caso o comando retorne 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

Juntando tudo

Embora isso seja desaprovado, não vejo como evitar o loop nas linhas de entrada, pois você precisa executar um comando muito específico para cada linha. Esteja ciente de que, para arquivos grandes, isso pode ser muito lento. Como seria o seu script com todos estes elementos:

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

informação relacionada