Awk: 동일한 블록에 있는 if 및 조건문

Awk: 동일한 블록에 있는 if 및 조건문

다음은 파일 이름이 'pretempsc.cfg'인지 확인하고 해당 내용을 있는 그대로 인쇄해야 하는 스크립트에 대한 코드입니다. . 다른 파일의 경우에만 'abc 비활성화 ...'로 시작하는 줄을 'no abc ...'로 수정해야 합니다.

    #!/bin/sh
    IN_FILE=$1
    OUT_FILE=$2

    WhatFileIsIt() {
    awk -v filename=$IN_FILE '
    BEGIN {
        scnode = 0;
        if (filename == "pretempsc.cfg") {
            scnode = 1; }
    }
    {
        if (!scnode) {
            /^abc disable/ {
            print "no abc "$4"";
            next;
            }

            print;}
        }
        else {print}
    }
    '
    }

    cat $IN_FILE | WhatFileIsIt | cat > $OUT_FILE

이 스크립트를 실행하면 다음 오류가 발생합니다.

 awk: cmd. line:9:         /^abc disable/ {
 awk: cmd. line:9:                        ^ syntax error
 awk: cmd. line:16:     else {print}
 awk: cmd. line:16:     ^ syntax error

제가 찾아본 바로는 액션 블록 내에서 if 및 조건-액션을 사용하는 것이 잘못된 것 같지만 무엇이 잘못되었는지 정확히 알 수는 없습니다.

참고 사항: 쉘 스크립트 내에서 awk를 사용해야 하며 IN_FILE에서 자체 처리를 수행하는 WhatFileIsIt과 유사한 다른 함수가 많이 있습니다.

답변1

예, 해당 패턴 일치를 전체 문으로 변경해야 합니다 if.

if (/^abc disable/) {
    print "no abc "$4"";
    next;
}

( 는 전체 입력 라인을 포함하는 의 /pattern/약어입니다 .)$0 ~ /pattern/$0

print거기는 입력의 네 번째 열만 인쇄하므로 no abcjust abc disable foo bar doo로 바뀐다는 점에 유의하세요 no abc bar. 이것이 당신이 원하는 것인지 잘 모르겠습니다.


그 과정에서 다른 것들이 떠오릅니다... 너무 명백하거나 스크립트의 나머지 부분과 충돌하는 경우에는 무시해도 됩니다. (그리고 제가 너무 많은 실수를 저지르지 않았으면 좋겠습니다.)

끝 부분에 추가 오른쪽 중괄호가 있는 것 같고 print가장 깊은 조건의 들여쓰기가 약간 벗어난 것 같아서 약간 다시 작성합니다.

{
    if (!scnode) {
        if (/^abc disable/) {
            print "no abc " $4;
            next;
        }
        print;
    } else {
        print;
    }
}

그러나 여기에서 보면 특별한 작업이 수행되는 유일한 경우는 둘 다 !scnodetrue이고 /^abc disable/일치하는 경우이고, 다른 모든 경우에는 print. 따라서 우리는 다음과 같은 조건을 결합할 수 있습니다. &&(물론 서로 다른 유형의 파일 간의 구분은 더 이상 명확하지 않습니다.)

{
    if (!scnode && /^abc disable/) {
        print "no abc "$4"";
        next;
    } else {
        print;
    }
}

실행을 짧게 하는 a가 있기 때문에 next최종은 절 print없이도 유지될 수 else있으며 실제로 전체 코드 블록은 단지 an이므로 if조건을 기본 수준으로 떨어뜨리고 인쇄라는 무조건적인 기본 작업을 수행할 수 있습니다.

!scnode && /^abc disable/ {
    print "no abc "$4"";
    next;
}
1;

(물론 지금은 너무 압축되어 보일 수도 있습니다.)


또한 쉘 스크립트에서는 고양이를 귀찮게 할 필요가 없습니다. 고양이를 잠자기 상태로 두고 리디렉션을 위해 쉘만 사용하는 것이 좋습니다. (그리고 쉘 변수를 인용하십시오.)

 WhatFileIsIt < "$IN_FILE" > "$OUT_FILE"

해당 함수의 이름은 약간 혼란스럽습니다. 실제로 "무엇"에 대한 질문에 대답하지 않고 파일을 처리합니다. 아마도 ProcessFile?

IN_FILE그리고 함수에 대해 말하면, 해당 함수 는 로컬이 아닌 변수를 사용합니다 . 서로 다른 두 파일에 대해 함수를 실행해야 하는 경우 혼란스러울 수 있습니다. 쉘 스크립트 자체와 마찬가지로 함수는 매개변수를 사용하여 호출하고 함수 내부에 포함을 MyFunction foo만들 수도 있습니다.$1foo

그래서 나는 아마도 다음과 같은 일을 할 것입니다

ProcessFile() {
awk < "$1" -v filename="$1" '
[...]

(입력 리디렉션을 awk 명령줄 중간에 두든, 끝에 두든 상관없습니다.)

다음과 함께 사용:

ProcessFile "$IN_FILE" > "$OUT_FILE"

관련 정보