Разбор текстового файла и вывод его в новом формате

Я пытаюсь изучить парсеров файлов, используя сценарий оболочки, и у меня есть входной файл 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 

  • Как вставить текст после последней строки конфигурации?
  • Объедините 2 файла в одном с настраиваемой линией между
  • Как слить текст буквенных строк с числовыми строками в оболочке?
  • Как найти все соответствия регулярному выражению в строке
  • количество столбцов со значением 0 в строке / строке 230
  • Подведение строк с общим полем
  • Awk / bash Keep line containg только 3 поля
  • как печатать, если строка содержит определенный шаблон и не печатать, если она не содержит шаблон
  • 3 Solutions collect form web for “Разбор текстового файла и вывод его в новом формате”

    Ваш ввод кажется 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 

    Альтернатива 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 

    Pitfall:

     $ 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 
     perl -lane ' /^\s*\/\*/ and $,=",",next; print $a++,join ", ", grep /./, map { m!^/\*+\K(\S*)|([^*]*)(?=\*+/$)|(.+[^;]);?$! } @F ' 
    Interesting Posts

    Скрытый ключ ssh

    Как удалить текст, сопоставляющий определенные шаблоны из файла

    Скрипт для изменения файла конфигурации XML

    Описание mpack (-d) из переменной скрипта

    Есть ли способ выполнить код в командной строке (PS1) без использования обратных ссылок?

    Полное шифрование диска с помощью dm-crypt (без LUKS)

    Перенаправить выход хвоста в файл, а затем остановить, когда найдено совпадение

    Как я должен прийти к выводу, что мой видеодрайвер называется «intel»?

    Umask не соблюдается в файловой системе OCFS2

    Как мне увеличить прокрутку окна iterm (tmux) (не прокрутку строки)

    Перенаправить исходящий трафик в локальной сети, идущий на порт 443, на порт 80 или 8080 вместо

    Xorg-сервер 1.16+ на CentOS 7

    Стоит ли использовать параллельные процессы вместо forking в цикле for?

    Использование autoreconf без прав root на пути префикса приводит к поврежденному скрипту configure

    Что такое композитор (в общем), и который дает лучшую производительность (Ubuntu Mate 16.04)?

    Linux и Unix - лучшая ОС в мире.