Як я можу видалити весь текст із вкладених фігурних дужок у багаторядковий текстовий файл?


9

Це запитання походить від того, як я можу видалити весь текст із фігурних дужок у багаторядковий текстовий файл? (точно так само, але без вимог до гніздування).

Приклад:

This is {
{the multiline
text} file }
that wants
{ to {be
changed}
} anyway.

Стають:

This is 
that wants
 anyway.

Чи можливо це зробити за допомогою якоїсь однорядкової команди bash (awk, sed, perl, grep, cut, tr ... тощо)?

Відповіді:


13
$ sed ':again;$!N;$!b again; :b; s/{[^{}]*}//g; t b' file3
This is 
that wants
 anyway.

Пояснення:

  • :again;$!N;$!b again

    Це читається у всьому файлі.

    :againє етикеткою. Nчитає в наступному рядку і $!Nчитає в наступному рядку за умови, що ми вже не в останньому рядку. $!b againгілки назад до againмітки за умови, що це не останній рядок.

  • :b

    Це визначає мітку b.

  • s/{[^{}]*}//g

    Це видаляє текст у дужках, доки текст не містить внутрішніх дужок.

  • t b

    Якщо вищезазначена команда заміни призвела до зміни, поверніться до мітки b. Таким чином команда заміщення повторюється, поки всі групи брекетів не будуть видалені.


3

Підхід Perl:

$ perl -F"" -a00ne 'for (@F){$i++ if /{/; $i||print; $i-- if /}/}' file
This is 
that wants
 anyway

Пояснення

  • -a: вмикає автоматичне розбиття на роздільник файлів, заданий -Fв @Fмасив.
  • -F"": встановлює порожній роздільник поля введення, в результаті чого кожен елемент @Fбуде одним із символів введення.
  • -00: увімкніть "режим абзацу", де "рядок" визначається як два послідовних символи нового рядка. Це означає, що весь файл у цьому випадку буде розглядатися як один рядок. Якщо у вашому файлі може бути багато абзаців, і дужки можуть охоплювати кілька абзаців, скористайтеся -0777натомість.
  • -ne: прочитайте вхідний файл і застосуйте заданий сценарій -eдо кожного рядка.

Сам сценарій насправді досить простий. Лічильник збільшується по одному щоразу, коли a {бачиться і зменшується по одному на кожного }. Це означає, що коли лічильник дорівнює 0, ми не знаходимося в дужках і повинні друкувати:

  • for (@F){}: зробіть це для кожного елемента @F, кожного символу в рядку.
  • $i++ if /{/;: приріст $iна один, якщо цей символ є a{
  • $i||print;: друк, якщо $iне встановлено (0 вважається не встановленим).
  • $i-- if /}/: декремент $iна один, якщо цей символ є a}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.