Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > У кого есть скрипт для проверки нумерации пунктов?


Автор: Suppir 4.10.2009, 09:08
Документ имеет логическую структуру и разбит на пункты, подпункты и т.д.:

1. Сделать то-то
2. Сделать то-то
2.1. Сделать то-то
2.2. Сделать то-то
3. Сделать то-то
4. Сделать то-то

Кроме точек возможно отделение скобками: 1) 2) 3)
Также возможно перечисление букв: а) б) в)
Возможно до 3-х уровней подпунктов: 1.1.1.

У кого-нибудь есть скрипт, проверяющий правильность нумерации?

Автор: Suppir 4.10.2009, 09:46
Для простейших случаев: 1. 2. 3. 
я написал, а вот на более сложных вариантах появляется много нюансов

Автор: amg 5.10.2009, 09:29
Вот для случая с числами и точками (вложенность не важна):
Код
my $prev_item = '';
while (<>) {
  m/^\s*((?:\d+\.)+)\s/ || next;
  my $item = $1;
  my @next_items = next_items($prev_item);
  die "Bad $item at line $.\nWas $prev_item Expect @next_items\n" 
    unless grep {$item eq $_} @next_items;
  $prev_item = $item;
}

sub next_items {
  my $prev_item = "$_[0]0.";
  my @parts = split /\./, $prev_item;
  my @next_items;
  while (@parts) {
    my $last_part = pop(@parts)+1;
    push @next_items, [@parts,"$last_part."];
  }
  return map {join '.', @$_} @next_items;
}


Автор: Suppir 5.10.2009, 10:55
Спасибо! Я попробую на работе и отпишусь позже smile

Автор: Suppir 6.10.2009, 13:24
Скрипт находит лишнее:

Bad 1. at line 254
Was 2. Expect 2.1. 3.
Bad 1. at line 422
Was 3. Expect 3.1. 4.
Bad 1. at line 470
Was 7. Expect 7.1. 8.
Bad 1. at line 516
Was 4. Expect 4.1. 5.
Bad 1. at line 637
Was 2. Expect 2.1. 3.
Bad 1. at line 788
Was 2. Expect 2.1. 3.
Bad 1. at line 967
Was 4. Expect 4.1. 5.
Bad 1. at line 1436
Was 3. Expect 3.1. 4.
Bad 1. at line 1450
Was 2. Expect 2.1. 3.
Bad 1. at line 1578
Was 5. Expect 5.1. 6.
Bad 1. at line 1692
Was 2. Expect 2.1. 3.
Bad 1. at line 1795
Was 6. Expect 6.1. 7.
Bad 1. at line 1865
Was 3. Expect 3.1. 4.
Bad 1. at line 1945
Was 2. Expect 2.1. 3.
Bad 1. at line 2622


т.е. если есть перечисление: 
1. 
2.
3.
то скрипт ожидает после "1."  "1.1" и т.п.


я сделал немножко другим алгоритмом:

while(<IN>){
 if(/^\s+(\d+)\.\D]/){
    if ($1==$com && $1!=1){
         print OUT "ошибка $."} 
}

но при этом скрипт ловит только самые простые случаи:
1.
2.
2.
3.
4.

Автор: amg 6.10.2009, 15:38
Цитата(Suppir @  6.10.2009,  13:24 Найти цитируемый пост)
Скрипт находит лишнее:
Что значит лишнее? Насколько я понимаю, у Вас встречается что-то вроде 

1. 
...
2.
...
1.  line 254

и скрипт говорит, что после 2. могут следовать либо 2.1. либо 3.  а не 1.
Или если 1.  в строке 254 не начинает пункт списка, то как это отличить? (приведите кусок текста)


Автор: Suppir 7.10.2009, 08:53
amg, возможно, я как-то неправильно его реализовал. 
Кроме задачи поиска, необходимо было отсекать НЕ ошибки.
Например, в тексте может быть:

1. Утвердить список...
2. Изменить пункты 1 - 2 постановления N, изложив их в следующей редакции
"1. Сделать то-то     # эти места, ограниченные кавычками, за ошибки не считаются
2. Сделать то-то;".   # так как относятся к другим документам
3. Утвердить положение...
3. Ответственность... # а вот это ошибка

Я залил небольшой фрагмент текста (2 мб нужно скачать), последнюю версию скрипта и лог найденых ошибок.
http://slil.ru/28051690

т.е. на данный момент скрипт находит только ошибки вида:
1.
2.
3.
3. Ошибка

или 
1)
2)
2) Ошибка
3)

Добавлено @ 08:55
Если Вы сможете поймать те же самые ошибки своим алгоритмом, то дайте знать, пожалуйста.

Автор: amg 7.10.2009, 12:12
Не, разбираться неохота: слишком большой файл, куча служебных слов, тоже, наверное, имеющих значение, в нем, похоже, много документов, т.е. нумерация не сквозная...

Можете попробовать воспользоваться функцией из моего кода: она принимает строку с номером пункта (типа 2.1.) и возвращает список "правильных" следующих пунктов (2.2., 3., 2.1.1.). Если программа запоминает предыдущий пункт, то можно из него сгенерировать "правильные" идущие следом и сравнить их с текущим.

Или даже проще: написать функцию, решающую обратную задачу -- из текущего пункта генерировать строку, с которой должен начинаться предыдущий пункт (такая строка, очевидно, будет единственной, потому и проще).

Автор: Suppir 7.10.2009, 14:12
"слишком большой файл, куча служебных слов, тоже, наверное, имеющих значение, в нем, похоже, много документов, т.е. нумерация не сквозная..."
У меня такого "добра" несколько гигабайт smile

"из текущего пункта генерировать строку, с которой должен начинаться предыдущий пункт" - отличная идея, спасибо smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)