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

#html #regex #zsh #csplit

#HTML #регулярное выражение #zsh #csplit

Вопрос:

Я хотел бы разделить файл на несколько файлов на основе определенного шаблона регулярных выражений. Ниже я привожу воспроизводимый пример. Если есть более простое решение, я бы тоже приветствовал его!

У меня есть каталог со следующими файлами:

page1.html page2.html page3.html

Скажите, что мой page1.html выглядело это примерно так:

 <strong>Hello world</strong>

<p>ABC, Page (1 whatever).</p>
<p>Some text</p>

<p>DEF, Page (1 ummm what).</p>
<p>Some text</p>

<p>THE<em><strong><span class="underline">GHI</span></strong></em>JK <em><strong><span class="underline">the</span></strong></em>LMNOP<em><strong><span class="underline">Q</span></strong></em>RS.<p> ABC, Page (1).</p>
 

Я хочу разделить page1.html чтобы:

page1_0.html

 <strong>Hello world</strong>
 

page1_1.html

 <p>ABC, Page (1 whatever).</p>
<p>Some text</p>
 

page1_2.html

 <p>DEF,  Page (1 ummm what).</p>
<p>Some text</p>

<p>THE<em><strong><span class="underline">GHI</span></strong></em>JK <em><strong><span class="underline">the</span></strong></em>LMNOP<em><strong><span class="underline">Q</span></strong></em>RS.<p> ABC, Page (1).</p>
 

Мне нужен код, который идентифицирует строку со следующим шаблоном:

[0 to 10 characters in the beginning] , Page (1 [0 to 10 characters here]). </p>

В настоящее время у меня есть следующий код:

for filename in *.html; gcsplit -z -f "${filename%.*}_" --suffix-format="%d.html" $filename /'Page (1'/ '{*}'

Но это создает page1_3.html содержащий следующий текст:

 <p>THE<em><strong><span class="underline">GHI</span></strong></em>JK <em><strong><span class="underline">the</span></strong></em>LMNOP<em><strong><span class="underline">Q</span></strong></em>RS.<p> ABC, Page (1).</p>
 

Но когда я запускаю это:

 for filename in *.html; gcsplit -z -f "${filename%.*}_" --suffix-format="%d.html" $filename /'^.{0,10}, Page (1.{0,10}).</p>'/ '{*}'
 

Это просто выводит файл page1_0.html .

В чем проблема с моим регулярным выражением? Существуют ли какие-либо альтернативные способы достижения того, что я пытаюсь сделать?

Ответ №1:

Вы могли бы сделать это с помощью этого короткого скрипта Perl.

 #chunker.pl
use 5.022;
use strict;
use diagnostics;
use B "perlstring";

our $i = 0;
our $fmt = "page1_%d.html";
our $fn = sprintf $fmt, $i;

open our $fh, ">", $fn or die $!;
print "opened $fnn";
while (<<>>) {
  printf "read line $.: %sn", perlstring $_;
  if (m{^.{0,10}?, Page (1 [^)]{0,10}?).</p>}) {
    print "break matched line $.n";
    $fn = sprintf $fmt,   $i;
    open $fh, ">", $fn or die $!;
    print "opened $fnn";
  }
  print $fh $_;
}

 

С принтами:

 $ perl chunker.pl page1.html

opened page1_0.html
read line 1: "<strong>Hello world</strong>n"
read line 2: "n"
read line 3: "<p>ABC, Page (1 whatever).</p>n"
break matched line 3
opened page1_1.html
read line 4: "<p>Some text</p>n"
read line 5: "n"
read line 6: "<p>DEF, Page (1 ummm what).</p>n"
break matched line 6
opened page1_2.html
read line 7: "<p>Some text</p>n"
read line 8: "n"
read line 9: "<p>THE<em><strong><span class="underline">GHI</span></strong></em>JK <em><strong><span class="underline">the</span></strong></em>LMNOP<em><strong><span class="underline">Q</span></strong></em>RS.<p> ABC, Page (1).</p>n"
read line 10: "n"
read line 11: "n"



$ for f in page1_*.html; do echo "$f:"; cat $f; echo; done;
page1_0.html:
<strong>Hello world</strong>


page1_1.html:
<p>ABC, Page (1 whatever).</p>
<p>Some text</p>


page1_2.html:
<p>DEF, Page (1 ummm what).</p>
<p>Some text</p>

<p>THE<em><strong><span class="underline">GHI</span></strong></em>JK <em><strong><span class="underline">the</span></strong></em>LMNOP<em><strong><span class="underline">Q</span></strong></em>RS.<p> ABC, Page (1).</p>


 

Я думаю, что проблема с вашим регулярным выражением заключалась в том, что вам нужно было не жадное сопоставление.

.{0,10}? минимум от нуля до десяти
, Page (1
[^)]{0,10}? минимум от нуля до десяти не закрывающих скобок
).</p> затем закрытие

HTH

Комментарии:

1. Я запустил сценарий perl, и результаты состояли из page1_0.html (заголовок) и page1_1.html (остальная часть страницы).

2. Я просто повторил его с моим точным кодом из ответа и вашего образца текста, и я получил тот же результат. Вы пробовали это с точным примером текста из вашего вопроса?

3. Неважно. Я попробовал еще раз, и это сработало. Не уверен, что произошло в первый раз. Извините за это.

4. Вы также можете сжать это до однострочного, чтобы сделать это в командной строке.

Ответ №2:

^.{0,10}, Page (1.{0,10}).</p>

В чем проблема с моим регулярным выражением?

Это не форматирование POSIX. Попробуйте ^.{0,10}, Page (1.{0,10}).</p> .

Это / / только потому, что он должен использоваться в качестве /REGEXP/[offset] аргумента для csplit инструмента. Возможно, вы захотите изменить это последнее . . значение на, чтобы оно соответствовало вашему символу точки.

Комментарии:

1. Я использовал ^.{0,10}, Page (1.{0,10}).</p> и получил page1_0.html файл (только с заголовком hello world) и page1_1.html (вместе с остальной частью страницы).

2. Что происходит с [^>]*[^<]* ?

3. После выполнения ^.{0,50}Page (1 я был более или менее в состоянии достичь того, что я пытался сделать.