Все задачи

Приключения каталогизатора

09 Jul 2013

Программист писал скрипт, который парсит описания книг из файла. Данные выглядят примерно так:

17914003 Льюс Кэрролл. Алиса в стране чудес
7459350 Karl Marx. Das Kapital
3669011 Damian Conway. Perl Best Practices 
7304332 Лев Толстой. Война и мир
7364216 Индийские сказки

Получился вот такой код:

use strict;
use warnings;

# в файле книги записаны в формате:
# <id> <автор>. <название>
# автора может не быть
my @books;
while (my $title = <>) {
    chomp $title;
    next if $title eq '';
    $title =~ s/^([0-9]+)\s*//;
    my $id = $1;
    $title =~ s/^(.+?)\.\s*//;
    my $author = $1 || '';
    push @books, {
        id => $id,
        title => $title,
        author => $author,
    };
}
# ...

Все хорошо, но у некоторых книг были проблемы с авторами…

Кстати, про этого программиста есть еще история: Книжки без картинок.

Подсказка

Показать

У некоторых книг вместо автора проставлялись какие-то числа.

Подсказка-2

Показать

Программист добавил отладочную печать:

print join "\n", map {"$_->{title} - $_->{author}"} @books;

Результат:

Алиса в стране чудес - Льюс Кэрролл
Das Kapital - Karl Marx
Perl Best Practices  - Damian Conway
Война и мир - Лев Толстой
Индийские сказки - 7364216

Разоблачение

Показать

Проблема в том, что переменные $1, $2 и т.п. не сбрасываются, если очередное сопоставление с регулярным выражением не поймало ни одной группы.

Поэтому даже если у книги не был указан автор, в переменной $1 все равно содержалась непустая строчка, оставшаяся от предыдущего успешного сопоставления (в нашем случае – от поиска id книги).