Awk: 同じブロック内の if 文と条件文

Awk: 同じブロック内の if 文と条件文

以下は、ファイル名が 'pretempsc.cfg' であることを確認し、その内容をそのまま印刷するスクリプトのコードです。他のファイルの場合のみ、'abc enable ...' で始まる行を '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 と condition-action の使用が間違っているのではないかと思われますが、何が間違っているのか正確にはわかりません。

注意: シェル スクリプト内では awk を使用する必要があります。また、IN_FILE で独自の処理を実行する WhatFileIsIt に似た他の関数も多数あります。

答え1

はい、パターン マッチを完全なifステートメントに変更する必要があります。

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

(/pattern/は の省略形です$0 ~ /pattern/。 には$0入力行全体が含まれます。)

printは、 の後の 4 番目の列のみを印刷するためno abcabc 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;
    }
}

next実行を短縮する があるため、final は 節printなしでも実行できますelse。実際、コード ブロック全体が であるため、if条件をメイン レベルにドロップし、無条件のデフォルト アクションである印刷を続行できます。

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

(もちろん、これでは少し凝縮しすぎているように見えるかもしれません。)


また、シェル スクリプトでは、cats を煩わせる必要はありません。cats をスリープ状態にしておき、リダイレクトにはシェルだけを使用する方がよいでしょう。(シェル変数を引用符で囲みます。)

 WhatFileIsIt < "$IN_FILE" > "$OUT_FILE"

この関数の名前は少し紛らわしく、実際には「何を」という質問には答えず、ファイルを処理します。おそらく次のようなものでしょうProcessFile

さて、関数について言えば、その関数は変数 を使用しますIN_FILEが、これは関数にローカルではありません。2 つの異なるファイルに対して関数を実行する必要がある場合、混乱する可能性があります。シェル スクリプト自体と同様に、関数もパラメーターを受け取ることができ、 を呼び出すとMyFunction foo、関数内に $1が含まれます。foo

だから私はこうするかもしれない

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

(入力リダイレクトを awk コマンドラインの途中に置くか最後に置くかは問題ではありません。)

一緒に使用:

ProcessFile "$IN_FILE" > "$OUT_FILE"

関連情報