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에 있다고 가정하면 날짜는 두 번째 열인 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

관련 정보