
たとえば、構造体からフィールドを抽出しようとしています。
typedef struct newstruct {
long id;
uint32_t vtid;
struct HN* next;
} HashNode;
sed/awkを使用して構造体名を抽出し、その後に区切り文字でフィールドを抽出したい。
newstruct HashNode: long id, uint_32 vtid, struct HN* next
答え1
を使用するとかなり簡単になりますがawk
、 を使用するとおそらく実行可能ですsed
。
を使用するとawk
、各行で設定/リセットされる状態がありtypedef
、各行は右中括弧で終わります。適切なawk
スクリプトは次のようになります。
BEGIN {
state = 0;
typedef="";
fields="";
}
/typedef[ ]+struct/{
state = 1;
typedef=$3;
next;
}
/}.*;/ {
if (state != 0) {
sub("^.*}[ ]*","",$0);
sub(";","",$0);
sub(",$","",fields);
printf "%s %s: %s\n", typedef, $0, fields;
state = 0;
fields = "";
typedef = "";
}
next;
}
(state == 1){
gsub("[ ]+"," ", $0);
gsub(";",",",$0);
fields = fields $0;
next;
}
ここで、角かっこ[
と]
タブはスペースとタブを囲みます (移植性を高めるため)。スクリプトには 4 つの部分があります。
- アクション
BEGIN
は変数を初期化します(厳密には必要ではありませんが、一部の awk は初期化されていない変数に対して若干異なる処理を行います) - 行に一致するパターンは
typedef
、 の後に空白と単語 が続きますstruct
。行には少なくとも 3 つのフィールドが必要であり、3 番目は typedef の名前として使用されます。 - 閉じ中括弧に一致するパターン。ファイルに他の内容が含まれている場合に備えて、アクションは が
state
設定されているかどうかを確認します。 は$0
現在の行です。最初の置換では、関心のある単語の前のすべてが削除され、2 番目の置換では、それに続くセミコロンが削除されます。3 番目の置換では、4 番目のアクション (以下) から取得した変数の後のカンマがfields
空の文字列に変更されます。 - 他のすべての行に一致するパターンいつ
state
が設定されています。前のアクションと同様に、これは置換を使用して、最初に複数の空白を 1 つの空白に減らし、次に末尾のセミコロンをカンマに変更することで、不要な部分を削除します。
そのファイルfoo.awk
と入力データを呼び出してfoo.in
、次のように awk を使用します。
awk -f foo.awk <foo.in
次のような行を一致させたい場合:
struct foo {
それよりも
typedef struct foo {
パターンは次のように記述できる
/^([ ]*typedef)?[ ]+struct[ ]+/{
(ここでも、角括弧内にはスペースとタブがそのまま入っています)。括弧はグループ疑問符は?
それを0回以上繰り返すことを意味します。({
線上の部分は実際にはアクションただし、指定されたスクリプトの行と一致するようにそのまま残しました。
参考文献:
- awk - パターンスキャンおよび処理言語(POSIX)
- 9.4 拡張正規表現(POSIX)
答え2
sed -rn '
/typedef struct ([[:alnum:]_]+)\s+\{/!b
s//\1/; h
:X
n
/}\s+([[:alnum:]_]+)/{
s//\1/
H
g
s/;//g
s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/\1 \5: \2, \3, \4/
p;b
}
s/\s*(.+);\s*/\1/
H
bX
' file
newstruct HashNode: long id, uint32_t vtid, struct HN* next