![Анализ текстового файла и вывод его в новом формате](https://rvso.com/image/109261/%D0%90%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%20%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%20%D0%B8%20%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%20%D0%B5%D0%B3%D0%BE%20%D0%B2%20%D0%BD%D0%BE%D0%B2%D0%BE%D0%BC%20%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B5.png)
Я пытаюсь изучить анализаторы файлов с помощью скрипта оболочки, и у меня есть входной файл
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
'