私はシェルスクリプトを使用してファイルパーサーを学習しようとしており、入力ファイルは
input.txt
次のようになっています。
int A[4]; /* 0 16*/
char B[15]; /* 16 31*/
/* Padding may be required here */
long int C[2]; /*32 8*/
上記を解析して、次の出力ファイルinput.txt
のような希望の形式にする方法はありますか?output.txt
0,int, A[4], 0, 16
1,char, B[16], 16,31
2,long int, C[2], 32, 8
答え1
入力は C に似ているようなので、理論的には C パーサーで解析する方がよいでしょう。正規表現を使用する場合、単純なタスクであっても、さまざまなスペースや複数行の入力などを処理する必要があります。問題は、C パーサーがコメントを解析しないことですが、どうやらあなたはコメントを解析したいようです。
以下は、サンプルの期待される出力を提供する Perl スクリプトです。
#!/usr/bin/perl -n
#
BEGIN { $i = 0; }
if (m!^\s*(.+)\s+([^ ]+);\s*/\*\s*(\d+)\s*(\d+)\s*\*/\s*$!)
{
print "$i,$1,$2,$3,$4\n";
$i+=1
}
このスクリプトを、script.pl
のフォルダーに保存する場合はinput.txt
、次のように使用します。
./script.pl < input.txt > output.txt
答え2
正規表現を使用しない awk の代替:
$ echo "int A[4]; /* 0 16*/" |awk '{gsub(/[/*;]/,"");for (i=1;i<=NF;i++) printf("%s, %s", (i==1?NR-1:""),(i==NF?$i"\n":$i))}'
#Output:
0, int, A[4], 0, 16
落とし穴:
$ echo "long int C[2]; /*32 8*/" |awk '{gsub(/[/*;]/,"");for (i=1;i<=NF;i++) printf("%s, %s", (i==1?NR-1:""),(i==NF?$i"\n":$i))}'
#Output
0, long, int, C[2], 32, 8
答え3
perl -lane '
/^\s*\/\*/ and $,=",",next;
print $a++,join ", ", grep /./, map { m!^/\*+\K(\S*)|([^*]*)(?=\*+/$)|(.+[^;]);?$! } @F
'