Я іноді хочу відповідати пробілу, але не новому рядку.
Поки що я вдавався [ \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
прекрасно працював у моєму випадку використання, який робив пошук / заміну в Блокноті ++ на 1 або більше суміжних просторах, які не є новими рядками. Нічого іншого (просто) не працювало.
\h
трохи нестандартним, це його включення MONGOLIAN VOWEL SEPARATOR
. Unicode не вважає це пробілом. З цієї причини Perl \h
відрізняється від POSIX blank
( [[:blank:]]
у Perl, \p{Blank}
на Java) та Java 8 \h
. Справді, це крайній випадок.
Використовуйте подвійний мінус:
/[^\S\r\n]/
Тобто, не-пробільний простір (з великої літери доповнює) або не-перевезення-повернення чи не-нова лінія. Розподіляючи зовнішнє не ( тобто доповнення ^
до класу символів) із законом Де Моргана , це еквівалентно "пробілу, але не поверненню каретки чи новій лінії ". Включаючи як \r
і \n
в шаблон, правильно обробляє всі конвенції Unix (LF), класичні Mac OS (CR) та DOS-ish (CR LF) newline .
Не потрібно сприймати моє слово за це:
#! /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:]]
який відповідає будь-яким горизонтальним пробілам ( пробіли та вкладки ). Цей клас chracter POSIX буде працювати на BRE ( базові регулярні вирази ), ERE ( розширене регулярне вираження ), PCRE ( Perl сумісна регулярна експресія ).
Що ви шукаєте, це blank
клас символів POSIX . У Perl це посилання:
[[:blank:]]
на Java (не забудьте включити UNICODE_CHARACTER_CLASS
):
\p{Blank}
Порівняно з аналогічним \h
, POSIX blank
підтримується ще кількома двигунами-регексами ( довідник ). Основна перевага полягає в тому, що його визначення зафіксовано в Додатку С: Властивості сумісності регулярних виразів Unicode та стандарт для всіх ароматів регулярного виразів, які підтримують Unicode. (Наприклад, Perl \h
вирішує додатково включити MONGOLIAN VOWEL SEPARATOR
.) Однак аргументом на користь \h
є те, що він завжди виявляє символи Unicode (навіть якщо двигуни не погоджуються), в той час як класи символів POSIX часто за замовчуванням ASCII -тільки (як у Java).
Але проблема полягає в тому, що навіть дотримання Unicode не вирішує проблему на 100%. Розглянемо такі символи, які не вважаються пробілами в Unicode:
U + 180E МОНГОЛЬСЬКИЙ СЕПАРАТОР ВОЛУ
U + 200B ZERO WIDTH SPACE
U + 200C ZERO WIDTH НЕ ПРИЄДНАЙТЕСЬ
U + 200D ШІРНИЙ ПРИЄДНИЙ ЗЕРО
U + 2060 СЛОВНИЙ СПІЛЬНИК
U + FEFF ZERO ШИРОТИЙ НЕЗАПАДНИЙ ПРОСТОР
Вищезгаданий монгольський роздільник голосних не включений з того, що, мабуть, є вагомою причиною. Він, поряд з 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]
.