の代わりに、文字フィールドごとのモード ( )でsed
いつでも使用できます。awk
FS=""
awk 'BEGIN {
RS = "\n" ;
FS = "" ;
d = 0 ;
}
{
for (i=1; i<=NF; i++)
if ($i == "{") {
d++ ;
if (d == 1) printf "{\n"
} else
if ($i == "}") {
d-- ;
if (d == 0) printf "}"
} else
if (d == 0)
printf "%s", $i ;
if (d == 0) printf "\n"
}' INPUT-FILE(s)...
上記は、ペアの中括弧の内容、つまり関数と構造体の本体、配列の初期化などをスキップし、結果を標準出力に出力します。1 つ以上のファイルを指定できます。(ファイルを指定しない場合、標準入力からの入力が期待されます。)
現在のように、引用符やコメント内のブレースについて混乱するでしょう。これは同じ方法で修正できますが、かなり複雑になります。これは、ほとんどの方法を取得するための単なるハックです。
セミコロン ( ) を追加した;
ので、上記のスニペットのすべてを 1 つの長いコマンド ラインに詰め込むことができます。
スクリプトのロジックは非常に単純です。FS
入力のすべての文字が独自のフィールドになるように、空のフィールドセパレーター ( ) を使用します。ルールは、BEGIN
入力が処理される前に 1 回実行され、これを設定します。開発者向けの情報として、d = 0
必要に応じて初期化されていない変数が空またはゼロであると想定しているため、awk では必要ありませんが、初期化も行います。各入力文字の現在のブレースの深さを追跡します。
2 番目の中かっこで囲まれた式は、すべてのレコードごとに 1 回実行されます。を設定したのでRS = "\n"
、各行は個別の式になります。したがって、入力行ごとに 1 回実行されます。によりFS = ""
、その行の各文字は個別のフィールドになります。NF
レコードには$1
、 、$2
、 ..、$(NF-1)
、およびのフィールドがあります$NF
。3 部構成の if 句は、単に最も外側の中かっこを出力し、中かっこ内にないすべてのもの (つまり when d == 0
) を出力します。
このawk
スクリプトレットを拡張して、コメント、文字列、文字定数 (\047
単一引用符を参照するために使用します。スクリプトを で別のファイルに入れる場合を除きます#!/usr/bin/awk -f
) を含めたり、プリプロセッサ マクロを処理または無視したりできます。
少し複雑になり、数百行の awk スクリプトが必要になりますが、信頼性が高く、適度に高速であるはずです。これが可能な理由は、この特定のケースでの C のトークン化規則に従うのが簡単だからです。個人的には、他のすべてのユース ケースでは本格的な C lexer (語彙アナライザーまたはスキャナー) を使用します。そしておそらくこれも。
本格的な C 字句解析器を使用したい場合は、ネット上で自由に利用できるものが多数ありますが、C や C++ などのより高度な言語を使用する必要があります。すべてのコーナー ケースを処理したい場合は、C/C++ プリプロセッサも組み込む必要がありますが、これらのルールは簡単です (awk を使用しても)。