Saya terkadang ingin mencocokkan spasi putih tetapi tidak dengan baris baru.
Sejauh ini saya telah menggunakan [ \t]
. Apakah ada cara yang kurang canggung?
Saya terkadang ingin mencocokkan spasi putih tetapi tidak dengan baris baru.
Sejauh ini saya telah menggunakan [ \t]
. Apakah ada cara yang kurang canggung?
Jawaban:
Perl versi 5.10 dan yang lebih baru mendukung kelas karakter vertikal dan horizontal, \v
dan \h
, juga kelas karakter spasi putih generik\s
Solusi terbersih adalah menggunakan kelas karakter spasi putih horizontal\h
. Ini akan mencocokkan tab dan ruang dari set ASCII, ruang tanpa putus dari ASCII yang diperluas, atau salah satu dari karakter Unicode ini
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 ruang vertikal pola \v
kurang berguna, tapi cocok karakter ini
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
Ada tujuh karakter spasi putih vertikal yang cocok \v
dan delapan belas karakter horizontal yang cocok \h
. \s
cocok dengan dua puluh tiga karakter
Semua karakter spasi putih baik vertikal atau horizontal tanpa tumpang tindih, tetapi mereka bukan himpunan bagian yang tepat karena \h
juga cocok dengan U + 00A0 NO-BREAK SPACE, dan \v
juga cocok dengan U + 0085 LINE NEXT, yang keduanya tidak cocok dengan\s
\h
hanya berfungsi pada bahasa yang mendukung PCRE
.
[[:blank:]]
tidak cocok dengan ruang tanpa istirahat -
atau"\xA0"
\h
berfungsi dengan baik untuk use case saya yang sedang melakukan find / replace di Notepad ++ pada 1 atau lebih ruang baris non-baru yang bersebelahan. Tidak ada yang lain (sederhana) yang berfungsi.
\h
sedikit tidak standar adalah dimasukkannya MONGOLIAN VOWEL SEPARATOR
. Unicode tidak menganggapnya sebagai spasi putih. Untuk alasan itu, Perl \h
berbeda dari POSIX blank
( [[:blank:]]
dalam Perl, \p{Blank}
di Jawa) dan Java 8 \h
. Memang, ini kasus tepi.
Gunakan double-negatif:
/[^\S\r\n]/
Yaitu, bukan-bukan-spasi putih (ibukota S melengkapi) atau tidak-carriage-return atau tidak-newline. Mendistribusikan bagian luar tidak ( yaitu , pelengkap ^
dalam kelas karakter) dengan hukum De Morgan , ini setara dengan "spasi putih tetapi bukan carriage return atau newline." Termasuk keduanya \r
dan \n
dalam pola dengan benar menangani semua konvensi baris baru Unix (LF), Mac OS (CR) klasik, dan DOS-ish (CR LF) .
Tidak perlu mengambil kata saya untuk itu:
#! /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";
}
Keluaran:
"" => cocok "\ f" => cocok "\ t" => cocok "\ r" => tidak cocok "\ n" => tidak cocok
Perhatikan pengecualian tab vertikal, tetapi ini dibahas dalam v5.18 .
Sebelum menolak terlalu keras, dokumentasi Perl menggunakan teknik yang sama. Catatan kaki di bagian “Ruang Putih” perlrecharclass berbunyi
Sebelum Perl v5.18,
\s
tidak cocok dengan tab vertikal.[^\S\cK]
(Jelas) cocok dengan apa yang secara\s
tradisional dilakukan.
The bagian yang sama dari perlrecharclass juga menunjukkan pendekatan lain yang tidak akan menyinggung oposisi guru bahasa untuk double-negatif.
Di luar lokal dan aturan Unicode atau ketika /a
sakelar berlaku, " \s
cocok [\t\n\f\r ]
dan, mulai di Perl v5.18, tab vertikal \cK
,." Buang \r
dan \n
tinggalkan /[\t\f\cK ]/
untuk pencocokan spasi putih tetapi bukan baris baru.
Jika teks Anda adalah Unicode, gunakan kode yang mirip dengan sub di bawah ini untuk membuat pola dari tabel di bagian dokumentasi yang disebutkan di atas .
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;
}
Trik ganda negatif juga berguna untuk mencocokkan karakter alfabet juga. Ingat bahwa \w
cocok dengan "karakter kata," karakter dan digit alfabet dan garis bawah. Kami orang Amerika yang jelek kadang ingin menuliskannya sebagai, katakanlah,
if (/[A-Za-z]+/) { ... }
tetapi kelas karakter ganda-negatif dapat menghormati lokal:
if (/[^\W\d_]+/) { ... }
Mengekspresikan "karakter kata tetapi bukan angka atau garis bawah" dengan cara ini agak buram. Kelas karakter POSIX mengkomunikasikan maksud secara lebih langsung
if (/[[:alpha:]]+/) { ... }
atau dengan properti Unicode seperti yang disarankan szbalint
if (/\p{Letter}+/) { ... }
\r
, misalnya pada Windows, sehingga mempertimbangkan exluding mereka dari pertandingan juga: /[^\S\r\n]/
)
\h
tersedia.
Variasi jawaban Greg yang mencakup carriage return juga:
/[^\S\r\n]/
Regex ini lebih aman daripada /[^\S\n]/
tanpa \r
. Alasan saya adalah bahwa Windows menggunakan \r\n
baris baru, dan Mac OS 9 digunakan \r
. Anda tidak akan menemukannya \r
tanpa \n
saat ini, tetapi jika Anda menemukannya, itu tidak bisa berarti apa-apa selain baris baru. Jadi, karena \r
dapat berarti baris baru, kita juga harus mengecualikannya.
Regex di bawah ini akan cocok dengan spasi putih tetapi tidak dengan karakter garis baru.
(?:(?!\n)\s)
Jika Anda ingin menambahkan carriage return juga maka tambahkan \r
dengan |
operator di dalam lookahead negatif.
(?:(?![\n\r])\s)
Tambahkan +
setelah grup yang tidak menangkap untuk mencocokkan satu atau lebih spasi putih.
(?:(?![\n\r])\s)+
Saya tidak tahu mengapa kalian gagal menyebutkan kelas karakter POSIX [[:blank:]]
yang cocok dengan spasi putih spasi ( spasi dan tab ). Kelas chracter POSIX ini akan bekerja pada BRE ( Basic REgular Expressions ), ERE ( Extended Regular Expression ), PCRE ( Perl Kompatibel Regular Expression ).
Apa yang Anda cari adalah blank
kelas karakter POSIX . Dalam Perl itu dirujuk sebagai:
[[:blank:]]
di Jawa (jangan lupa untuk mengaktifkan UNICODE_CHARACTER_CLASS
):
\p{Blank}
Dibandingkan dengan yang serupa \h
, POSIX blank
didukung oleh beberapa mesin regex ( referensi ). Manfaat utama adalah bahwa definisi tersebut ditetapkan dalam Lampiran C: Properti Kompatibilitas Unicode Regular Expressions dan standar di semua rasa regex yang mendukung Unicode. (Dalam Perl, misalnya, \h
memilih untuk menyertakan tambahan MONGOLIAN VOWEL SEPARATOR
.) Namun, argumen yang mendukung \h
adalah bahwa ia selalu mendeteksi karakter Unicode (bahkan jika mesin tidak setuju dengan yang), sementara kelas karakter POSIX sering secara default ASCII -hanya (seperti di Jawa).
Tetapi masalahnya adalah bahwa bahkan tetap pada Unicode tidak menyelesaikan masalah 100%. Pertimbangkan karakter berikut yang tidak dianggap sebagai spasi putih di Unicode:
U + 180E MONGOLIAN VOWEL SEPARATOR
U + 200B NOL WIDTH SPACE
U + 200C NOL LEBIH BANYAK GABUNGAN
U + 200D NOL JOINER LEBAR
U + 2060 WORD JOINER
U + FEFF NOL DENGAN LEBIH BANYAK RUANG BREAK
Diambil dari https://en.wikipedia.org/wiki/White-space_character
Pemisah vokal Mongolia yang disebutkan di atas tidak termasuk untuk alasan yang mungkin bagus. Itu, bersama dengan 200C dan 200D, terjadi dalam kata-kata (AFAIK), dan karena itu melanggar aturan kardinal yang dipatuhi oleh semua spasi putih lainnya: Anda dapat melakukan tokenize dengannya. Mereka lebih seperti pengubah. Namun, ZERO WIDTH SPACE
, WORD JOINER
, dan ZERO WIDTH NON-BREAKING SPACE
(jika digunakan sebagai selain tanda byte-order) sesuai dengan aturan spasi dalam buku saya. Oleh karena itu, saya memasukkan mereka dalam kelas karakter spasi putih horizontal saya.
Di Jawa:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
tanda pada pertanyaan awal.
[\p{Blank}\u200b\u180e]
diperlukan. Diakui, masuk akal bahwa pemisah vokal tidak dianggap sebagai karakter spasi, tetapi mengapa ruang lebar nol tidak di kelas seperti \s
dan \p{Blank}
, mengalahkan saya.
m/ /g
cukup beri ruang / /
, dan itu akan berhasil. Atau gunakan \S
- ini akan menggantikan semua karakter khusus seperti tab, baris baru, spasi, dan sebagainya.
[\r\f]
.