Иногда я хочу найти пробел, но не перевод строки.
До сих пор я прибегал к [ \t]
. Есть ли менее неловкий путь?
Иногда я хочу найти пробел, но не перевод строки.
До сих пор я прибегал к [ \t]
. Есть ли менее неловкий путь?
Ответы:
Perl версии 5.10 и более поздних версий поддерживает вспомогательные классы по вертикали и горизонтали характер, \v
и \h
, а также общий пробельные класс символов\s
Самое чистое решение - использовать класс символов горизонтальных пробелов\h
. Это будет соответствовать символу табуляции и пробелу из набора ASCII, неразрывному пробелу из расширенного ASCII или любому из этих символов Unicode
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
Вертикальное пространство шаблон \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 NO-BREAK SPACE, а \v
также соответствуют U + 0085 NEXT LINE, ни один из которых не соответствует\s
\h
работает только на тех языках, которые поддерживает PCRE
.
[[:blank:]]
это не соответствует пространству без перерывов -
или"\xA0"
\h
прекрасно работает для моего варианта использования, который выполнял поиск / замену в Notepad ++ на 1 или более смежных пробелах, не начинающихся с новой строки. Ничто другое (простое) не сработало.
\h
слегка нестандартным, так это его включение MONGOLIAN VOWEL SEPARATOR
. Юникод не считает это пробелом. По этой причине Perl \h
отличается от POSIX blank
( [[:blank:]]
в Perl, \p{Blank}
в Java) и Java 8 \h
. Правда, это крайний случай.
Используйте двойной негатив:
/[^\S\r\n]/
То есть не-не-пробел (заглавная S дополняет) или не-возврат каретки или не-перевод строки. Распределение внешнего не ( т.е. дополнения ^
в классе символов) по закону Де Моргана , это эквивалентно «пробелу, но не возврату каретки или переводу строки». Включение обоих \r
и \n
в шаблон корректно обрабатывает все соглашения Unix (LF), классической Mac OS (CR) и DOS-ish (CR LF) .
Не нужно верить мне на слово:
#! /usr/bin/env perl
use strict;
use warnings;
use 5.005; # for qr//
my $ws_not_crlf = qr/[^\S\r\n]/;
for (' ', '\f', '\t', '\r', '\n') {
my $qq = qq["$_"];
printf "%-4s => %s\n", $qq,
(eval $qq) =~ $ws_not_crlf ? "match" : "no match";
}
Вывод:
"" => соответствовать "\ f" => соответствовать "\ t" => соответствовать "\ r" => нет совпадений "\ n" => нет совпадений
Обратите внимание на исключение вертикальной вкладки, но это рассматривается в v5.18 .
Прежде чем возражать слишком жестко, в документации Perl используется та же техника. Сноска в разделе «Пробелы» в perlrecharclass гласит:
До Perl v5.18
\s
не соответствовал вертикальной табуляции.[^\S\cK]
(неясно) соответствует тому, что\s
традиционно делали.
В том же разделе perlrecharclass также предлагаются другие подходы, которые не оскорбят противодействия учителей языка двойным негативам.
Вне локали и правил Unicode или когда действует /a
переключатель, « \s
соответствует [\t\n\f\r ]
и, начиная с Perl v5.18, вертикальная вкладка \cK
». Откажитесь \r
и \n
оставьте /[\t\f\cK ]/
для соответствующего пробела, но не перевод строки.
Если ваш текст - Unicode, используйте код, подобный приведенному ниже, для создания шаблона из таблицы в вышеупомянутом разделе документации .
sub ws_not_nl {
local($_) = <<'EOTable';
0x0009 CHARACTER TABULATION h s
0x000a LINE FEED (LF) vs
0x000b LINE TABULATION vs [1]
0x000c FORM FEED (FF) vs
0x000d CARRIAGE RETURN (CR) vs
0x0020 SPACE h s
0x0085 NEXT LINE (NEL) vs [2]
0x00a0 NO-BREAK SPACE h s [2]
0x1680 OGHAM SPACE MARK h s
0x2000 EN QUAD h s
0x2001 EM QUAD h s
0x2002 EN SPACE h s
0x2003 EM SPACE h s
0x2004 THREE-PER-EM SPACE h s
0x2005 FOUR-PER-EM SPACE h s
0x2006 SIX-PER-EM SPACE h s
0x2007 FIGURE SPACE h s
0x2008 PUNCTUATION SPACE h s
0x2009 THIN SPACE h s
0x200a HAIR SPACE h s
0x2028 LINE SEPARATOR vs
0x2029 PARAGRAPH SEPARATOR vs
0x202f NARROW NO-BREAK SPACE h s
0x205f MEDIUM MATHEMATICAL SPACE h s
0x3000 IDEOGRAPHIC SPACE h s
EOTable
my $class;
while (/^0x([0-9a-f]{4})\s+([A-Z\s]+)/mg) {
my($hex,$name) = ($1,$2);
next if $name =~ /\b(?:CR|NL|NEL|SEPARATOR)\b/;
$class .= "\\N{U+$hex}";
}
qr/[$class]/u;
}
Двойной отрицательный трюк также удобен для сопоставления буквенных символов. Помните , что \w
матчи «символы, слова» буквенные символы и цифры и подчеркивания. Мы, некрасивые американцы, иногда хотим написать это, скажем,
if (/[A-Za-z]+/) { ... }
но дважды отрицательный символьный класс может уважать локаль:
if (/[^\W\d_]+/) { ... }
Выражение «символ слова, но не цифра или подчеркивание» таким образом немного непрозрачно. Символьный класс POSIX сообщает намерение более напрямую
if (/[[:alpha:]]+/) { ... }
или со свойством Unicode как предложено szbalint
if (/\p{Letter}+/) { ... }
\r
, например , на Windows, так считают exluding те от матча , а также: /[^\S\r\n]/
)
\h
доступно.
Вариант ответа Грега, который также включает возврат каретки:
/[^\S\r\n]/
Это регулярное выражение безопаснее, чем /[^\S\n]/
без \r
. Я рассуждаю так: Windows использует \r\n
новые строки, а Mac OS 9 использует \r
. Вы вряд ли найдете \r
без нас в \n
наше время, но если вы найдете это, это не может означать ничего, кроме новой строки. Таким образом, поскольку \r
может означать новую строку, мы должны исключить ее тоже.
Приведенное ниже регулярное выражение будет соответствовать пробелам, но не символу новой строки.
(?:(?!\n)\s)
Если вы хотите добавить возврат каретки и затем добавить \r
с |
оператором внутри отрицательного предпросмотра.
(?:(?![\n\r])\s)
Добавьте +
после группы без захвата, чтобы соответствовать один или несколько пробелов.
(?:(?![\n\r])\s)+
Я не знаю, почему вы, люди, не упомянули класс символов POSIX, [[:blank:]]
который соответствует любым горизонтальным пробелам ( пробелы и табуляции ). Этот класс POSIX chracter будет работать с BRE ( базовые регулярные выражения ), ERE ( расширенное регулярное выражение ), PCRE ( регулярное выражение, совместимое с Perl ).
То, что вы ищете, это blank
класс символов POSIX . В Perl это упоминается как:
[[:blank:]]
в Java (не забудьте включить UNICODE_CHARACTER_CLASS
):
\p{Blank}
По сравнению с аналогом \h
, POSIX blank
поддерживается еще несколькими движками регулярных выражений ( ссылка ). Основным преимуществом является то, что его определение зафиксировано в Приложении C: Свойства совместимости регулярных выражений Unicode и стандарт для всех разновидностей регулярных выражений, поддерживающих Unicode. (Например, \h
в Perl выбирается дополнительное включение MONGOLIAN VOWEL SEPARATOR
.) Однако аргумент в пользу этого \h
заключается в том, что он всегда обнаруживает символы Unicode (даже если движки не согласны с какими), в то время как классы символов POSIX часто по умолчанию ASCII. только (как в Java).
Но проблема в том, что даже придерживание Unicode не решает проблему на 100%. Рассмотрим следующие символы, которые не считаются пробелами в Юникоде:
U + 180E монгольский разделитель гласных
U + 200B НУЛЕВОЕ ПРОСТРАНСТВО
U + 200C с нулевой шириной без соединения
U + 200D ZERO ШИРОКИЙ СОЕДИНИТЕЛЬ
U + 2060 WORD JOINER
U + FEFF с нулевой шириной неразрывного пространства
Вышеупомянутый монгольский разделитель гласных не включен, что, вероятно, является веской причиной. Это, наряду с 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]"
perl
тег в оригинальном вопросе.
[\p{Blank}\u200b\u180e]
требуются ужасы вроде . Правда, имеет смысл, что разделитель гласных не считается пробельным символом, но почему пробел нулевой ширины не в таких классах, как \s
и \p{Blank}
, лучше меня.
m/ /g
просто дайте место / /
, и это будет работать. Или используйте \S
- он заменит все специальные символы, такие как табуляция, новые строки, пробелы и так далее.
[\r\f]
.