Ich versuche, Dateiparser mithilfe von Shell-Skripten zu lernen, und ich habe meine Eingabedatei
input.txt
als
int A[4]; /* 0 16*/
char B[15]; /* 16 31*/
/* Padding may be required here */
long int C[2]; /*32 8*/
Gibt es eine Möglichkeit, das Obige in das von mir gewünschte Format zu analysieren , das wie diese Ausgabedatei input.txt
aussieht :output.txt
0,int, A[4], 0, 16
1,char, B[16], 16,31
2,long int, C[2], 32, 8
Antwort1
Ihre Eingabe scheint C-ähnlich zu sein, daher wäre es theoretisch besser, sie mit einem C-Parser zu analysieren. Wenn Sie reguläre Ausdrücke verwenden, müssen Sie selbst für einfache Aufgaben mit unterschiedlichen Leerzeichen, mehrzeiligen Eingaben usw. umgehen. Das Problem ist, dass C-Parser keine Kommentare analysieren und Sie dies anscheinend tun möchten.
Hier ist ein Perl-Skript, das die erwartete Ausgabe für Ihr Beispiel liefert.
#!/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
}
Wenn Sie dieses Skript script.pl
in dem Ordner speichern, in dem input.txt
es sich befindet, verwenden Sie es folgendermaßen:
./script.pl < input.txt > output.txt
Antwort2
Eine Awk-Alternative ohne reguläre Ausdrücke:
$ 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
Falle:
$ 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
Antwort3
perl -lane '
/^\s*\/\*/ and $,=",",next;
print $a++,join ", ", grep /./, map { m!^/\*+\K(\S*)|([^*]*)(?=\*+/$)|(.+[^;]);?$! } @F
'