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, если ложь, то F вместо R и F вместо O (для всех последовательных O) или S.

теперь из столбца нет я определю дату,

предположим, что в 1-й строке R находится на 5, поэтому дата будет в столбце № 3, т.е. 2-й,

для 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, то это ложь, если оно больше 0, то это истина.

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

По словам Валентина, после внесения нескольких изменений этот код, похоже, работает нормально.

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).

Извлечение значений 1-го и 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

Связанный контент