Рекомендации для обратной связи и подсказки по Perl Regex - PullRequest
0 голосов
/ 29 декабря 2010

Вчера я отправил вопрос: Perl Регулярное выражение удаляет двойные табуляции, разрывы строк, пробелы

При вашей большой помощи я смог решить проблему. Во-первых, решение:

$txt="\nRemove empty line at beg.".
     "\n\nRemove double empty line,      double spaces and ending space: \n".
     "\n and beginning. Same for tabs\t\n".
     "\tSame for Tab at beginning and multiple tabs \t\t\t and line break at end:\n\n\n";

# Works
$txt=~s/\r//gs; # * this is needed for actual $txt which may contain \r

# Following *should* replace it not with 1 space, but with 1 space or \t depending on input
$txt =~ s/[\t ]+/ /gs; # Replace duplicate whitespace mid-string with 1 space

$txt =~ s/[\t ]*$//gms; # Remove ending spaces/tabs
$txt =~ s/^[\t ]*//gms; # Remove starting spaces/tabs

$txt=~s/\n+/\n/gs;      # replace all runs of > 1 \n with a single \n

# clearly redundant
$txt =~ s/^$//ms;       # Remove completely empty lines ** does not work **
$txt =~ s/^\n//ms;       # Remove completely empty lines (beg.)
$txt =~ s/\n$//ms;       # Remove completely empty lines (end.)

Это работает , но не очень красиво.

Поэтому я хотел бы попросить две вещи: 1. Как я мог написать это как один лайнер? Я все еще хочу оставить комментарии, но я чувствую, что это супер неэффективно делать это во многих строках. Может я не прав, тогда все нормально как есть. 2. Это работает, но я чувствую, что это не близко к идеалу. Мне не нужно, чтобы это было идеально, но я хотел бы лучше понять регулярные выражения. Поэтому: есть ли рекомендации по улучшению? То есть есть ли что-нибудь избыточный или лишний здесь? 3. Есть ли в сети какое-нибудь учебное пособие по регулярным выражениям, которое дает представление обо всех возможностях регулярного выражения, а затем обучает их этим задачам?

1 Ответ

0 голосов
/ 29 декабря 2010

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

$txt =~ s/^$//ms; не работает, потому что $ соответствует либо в конце строки непосредственно перед новой строкой . Поэтому, если строка содержит только новую строку, она не будет соответствовать ей.

$txt =~ s/^\n//ms; не удаляет пустые строки в начале строки, потому что /m изменяет ^ и $, чтобы соответствовать началу и концу любой строки. Вам просто повезло с вашими тестовыми данными, что ваша строка начинается с новой строки, поэтому она соответствует этому и остановилась. То же самое со следующим. Используйте \A и \z или не спам /ms.

$txt =~ s{([\t ])+}{$1}g заменит последовательность вкладок или пробелов только одной вкладкой или пробелом. Однако с чем-то вроде "this \t that" он выберет последний символ.

Что приводит нас к тестированию.

use Test::More;

note "test tab and whitespace squeezing"; {
    is squeeze_whitespace("this  that"),   "this that";
    is squeeze_whitespace("this\t\tthat"), "this\tthat";
    is squeeze_whitespace("this \t that  up  ", "this that up";
}

note "test begin/end newline stripping"; {
    is squeeze_whitespace("\nfoo\n"), "foo", "newlines removed from the start and end";
    is squeeze_whitespace("foo\nbar"), "foo\nbar", "newlines not eaten if there's no newline at the start";
}

и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...