패턴 일치 후 루프가 성공할 때까지 에코하는 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"를 찾으면 열 번호를 가져오고 열 번호를 기반으로 명령을 수행해야 하며 이것이 사실이면 R 및 O 대신 L을 표시합니다. 또는 S가 거짓인 경우 R 대신 F를 사용하고 O(모든 연속 O에 대해) 대신 F를 사용하거나 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

관련 정보