Сопоставьте пробелы, но не новые строки
иногда я хочу соответствовать пробелам, но не новой строке.
до сих пор я прибегал к [ t]
. Есть ли менее неудобный способ?
6 ответов:
Perl версии 5.10 и более поздние поддерживают вспомогательные вертикальные и горизонтальные классы символов,
\v
и\h
, а также общий класс символов пробела\s
самое чистое решение-использовать горизонтальные пробельные символы класс персонажа
\h
. Это будет соответствовать табуляции и пробелу из набора ASCII, неразрывному пространству из расширенного ASCII или любому из этих символов ЮникодаU+0009 CHARACTER TABULATION U+0020 SPACE U+00A0 NO-BREAK SPACE (not matched by \s) U+1680 OGHAM SPACE MARK U+2000 EN QUAD U+2001 EM QUAD U+2002 EN SPACE U+2003 EM SPACE U+2004 THREE-PER-EM SPACE U+2005 FOUR-PER-EM SPACE U+2006 SIX-PER-EM SPACE U+2007 FIGURE SPACE U+2008 PUNCTUATION SPACE U+2009 THIN SPACE U+200A HAIR SPACE U+202F NARROW NO-BREAK SPACE U+205F MEDIUM MATHEMATICAL SPACE U+3000 IDEOGRAPHIC SPACE
The вертикальное пространство шаблон
\v
менее полезно, но соответствует этим символамU+000A LINE FEED U+000B LINE TABULATION U+000C FORM FEED U+000D CARRIAGE RETURN U+0085 NEXT LINE (not matched by \s) U+2028 LINE SEPARATOR U+2029 PARAGRAPH SEPARATOR
есть семь вертикальных символов пробела, которые соответствуют
\v
и восемнадцать горизонтальных, которые соответствуют\h
.\s
соответствует двадцати трем символамвсе символы пробела либо вертикальный или горизонтальный без перекрытия, но они не являются правильными подмножествами, потому что
\h
также соответствует U + 00A0 без перерыва пространства, и\v
также соответствует U + 0085 следующая строка, ни одна из которых не соответствует\s
используйте двойное отрицание:
/[^\S\n]/
чтобы избежать различий в платформе предупрежден о в perlport относительно отображений
\r
и\n
:/[^\S\x0a\x0d]/
то есть, не-не-пробел или не-новая строка и аналогично для шаблона, который исключает CR и NL.
распределение внешнего не (т. е., дополняющего
^
в классе символов) с закон де Моргана, это равносильно "пробел, а не возврат каретки и не новая строка", но не верьте мне на слово:#! /usr/bin/env perl use strict; use warnings; use 5.005; # for qr// my $ws_not_nl = qr/[^\S\x0a\x0d]/; for (' ', '\f', '\t', '\r', '\n') { my $qq = qq["$_"]; printf "%-4s => %s\n", $qq, (eval $qq) =~ $ws_not_nl ? "match" : "no match"; }
выход:
" " => match "\f" => match "\t" => match "\r" => no match "\n" => no matchобратите внимание на исключение вертикальной вкладки, но это адресовано в v5. 18.
этот трюк также удобен для сопоставления буквенных символов. Помните, что
\w
соответствует "символам слова", буквенным символам, но и цифры и подчеркивания. Мы уродливые-американцы иногда хотят написать это как, скажи,if (/^[A-Za-z]+$/) { ... }
но двойной отрицательный символьный класс может уважать локаль:
if (/^[^\W\d_]+$/) { ... }
это немного непрозрачно, поэтому класс символов POSIX может быть лучше выражать намерение
if (/^[[:alpha:]]+$/) { ... }
или szbalint предложил
if (/^\p{Letter}+$/) { ... }
вариант ответ Грега что включает в себя возврат каретки тоже:
/[^\S\r\n]/
это регулярное выражение безопаснее, чем
/[^\S\n]/
С\r
. Моя аргументация заключается в том, что Windows использует\r\n
для новых строк и Mac OS 9 используется\r
. Вы вряд ли найдете\r
без\n
в настоящее время, но если вы найдете его, это не может означать ничего, кроме новой строки. Таким образом, поскольку\r
может означать новую строку, мы должны также исключить его.
то, что вы ищете, это POSIX
blank
класс персонажа. В Perl он упоминается как:[[:blank:]]
в Java (не забудьте включить
UNICODE_CHARACTER_CLASS
):\p{Blank}
по сравнению с аналогичным
\h
, POSIXblank
поддерживается еще несколькими движками регулярных выражений (ссылка). Основным преимуществом является то, что его определение закреплено в приложение C: свойства совместимости регулярных выражений Юникода и все ароматы тестирую которые поддерживают Юникод. (В Perl, например,\h
выбирает дополнительно включитьMONGOLIAN VOWEL SEPARATOR
.) Однако аргумент в пользу\h
заключается в том, что он всегда обнаруживает символы Unicode (даже если движки не согласны с этим), в то время как классы символов POSIX часто по умолчанию используются только ASCII (как в Java).но проблема в том, что даже придерживаясь Unicode не решает проблему на 100%. Рассмотрим следующие символы, которые не считаются пробелами в Юникод:
- U+180E МОНГОЛЬСКИЙ РАЗДЕЛИТЕЛЬ ГЛАСНЫХ
- U + 200B НУЛЕВАЯ ШИРИНА ПРОСТРАНСТВА
- U + 200C НУЛЕВАЯ ШИРИНА NON-JOINER
- U+200D НУЛЕВАЯ ШИРИНА СТОЛЯРА
- U + 2060 СЛОВО СТОЛЯР
U + FEFF НУЛЕВАЯ ШИРИНА НЕРАЗРЫВНОГО ПРОСТРАНСТВА
взято из https://en.wikipedia.org/wiki/White-space_character
вышеупомянутый монгольский гласный разделитель не включен, что, вероятно, является веской причиной. Он, наряду с 200C и 200D, встречается в словах (AFAIK) и поэтому нарушает основное правило, которому подчиняются все остальные пробелы: вы можете маркировать его. Они больше похожи на модификаторы. Однако,
ZERO WIDTH SPACE
,WORD JOINER
иZERO WIDTH NON-BREAKING SPACE
(если он используется в качестве отличного от знака порядка байтов) соответствует правилу пробелов в моей книге. Поэтому я включаю их в свой класс символов горизонтальных пробелов.В Java:
static public final String HORIZONTAL_WHITESPACE = "[\p{Blank}\u200B\u2060\uFFEF]"
ниже регулярное выражение будет соответствовать пробелам, но не нового символа строки.
(?:(?!\n)\s)
если вы хотите добавить возврат каретки и затем добавить
\r
С|
оператор внутри отрицательного lookahead.(?:(?![\n\r])\s)
добавить
+
после группы без захвата, чтобы соответствовать одному или нескольким пробелам.(?:(?![\n\r])\s)+
Я не знаю, почему вы, люди, не упомянули класс символов POSIX
[[:blank:]]
который соответствует любым горизонтальным пробелам (пробелы и знаки табуляции). Этот класс POSIX chracter будет работать на BRE (Основные Регулярные Выражения), где(Расширенное Регулярное Выражение), PCRE (Perl Совместимое Регулярное Выражение).