Boşluğu eşleştir, ancak yeni satırları eşleştir


277

Bazen boşlukla eşleşmek istiyorum ancak satırsonu ile eşleşmemek istiyorum.

Şimdiye kadar başvuruyordum [ \t]. Daha az garip bir yol var mı?


4
BTW, bu karakterler aynı zamanda "boşluk" şunlardır: [\r\f].
Eugene Yarmash

2
@eugeney hala form beslemeleri yapıyor mu? (\ f's)
Aran Mulholland

1
@AranMulholland: Karakter odaklı bir yazıcıya sahip olan herkes. Çoğu yazıcı, PostScript'in yanı sıra Hewlett Packard arabiriminin adı ne olursa olsun bir karakter moduna sahiptir ve bir sayfa atmak için bir form feed'i gönderirsiniz.
Borodin

1
@Borodin Hewlett Packard's, PCL (Yazıcı Kontrol Dili) olarak adlandırılır.
CB_Ron

Yanıtlar:


182

Perl sürüm 5.10 ve üzeri, yan dikey ve yatay karakter sınıflarını \vve \hgenel boşluk karakter sınıfını destekler\s

En temiz çözüm yatay boşluk karakter sınıfını kullanmaktır \h. Bu, ASCII kümesinden sekme ve boşluk, genişletilmiş ASCII'den kopmayan boşluk veya bu Unicode karakterlerden herhangi biriyle eşleşir

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

Dikey boşluk desen \vaz yararlı olduğunu, ancak bu karakterleri eşleşir

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

Eşleşen yedi dikey boşluk karakteri ve eşleşen \von sekiz yatay karakter vardır \h. \syirmi üç karakterle eşleşir

Tüm boşluk karakterleri üst üste binmeden dikey veya yataydır , ancak uygun alt kümeler değildir, çünkü \hU + 00A0 NO-BREAK SPACE ile \veşleşir ve ayrıca ikisi tarafından eşleşmeyen U + 0085 NEXT LINE ile eşleşir\s


7
\hyalnızca destekleyen dillerde çalışır PCRE.
Avinash Raj

14
@AvinashRaj: Bu soru kesinlikle PCRE'yi destekleyen Perl hakkında
Borodin

2
@AvinashRaj: Aradaki boşlukla eşleşmiyor [[:blank:]]-  veya"\xA0"
Borodin

6
\hNotepad ++ 1 veya daha fazla bitişik olmayan yeni satır boşlukları üzerinde bir bul / değiştir yapan benim kullanım durumum için mükemmel çalıştı bahsetmek istiyorum . Başka hiçbir şey işe yaramadı.
squidbe

8
Perl'i \hbiraz standart dışı yapan şey, dahil edilmesidir MONGOLIAN VOWEL SEPARATOR. Unicode boşluk olarak değerlendirmez. Bu nedenle Perl \h, POSIX blank( [[:blank:]]Perl'de, \p{Blank}Java'da) ve Java 8'den farklıdır \h. Kuşkusuz, bu bir uç durum.
Aleksandr Dubinsky

362

Çift negatif kullanın:

/[^\S\r\n]/

Yani, boşluk değil (başkent S tamamlar) veya satırbaşı veya satırsonu değil. Değil dış Dağıtma ( yani , tamamlayıcı ^birlikte karakter sınıfında) De Morgan yasa , bu eşdeğerdir “boşluk değil satırbaşı veya satır.” Hem dahil \rve \nklasik Mac OS (CR) ve DOS imsi (CR LF), desende doğru Unix (LF) tüm kolları yeni satır konvansiyonlar .

Benim sözüme gerek yok:

#! /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";
}

Çıktı:

"" => eşleşme
"\ f" => eşleme
"\ t" => eşleme
"\ r" => eşleşme yok
"\ n" => eşleşme yok

Dikey sekmenin hariç tutulduğuna dikkat edin , ancak bu v5.18'de ele alınmaktadır .

Çok sert itiraz etmeden önce, Perl belgeleri aynı tekniği kullanır. Bir dipnot perlrecharclass ait “Boşluk” bölümünde okur

Perl v5.18'den önce \sdikey sekmeyle eşleşmiyordu. [^\S\cK](belirsiz) \sgeleneksel olarak yapılanlarla eşleşir .

Perlrecharclass aynı bölümde ayrıca çift negatifler için dil öğretmenlerinin muhalefet rahatsız olmaz diğer yaklaşım önerir.

Zaman dışında yerel ve Unicode kuralları veya /aanahtar etkisi olduğu “ \skibrit [\t\n\f\r ]ve, Perl v5.18, dikey sekmede başlayan \cK.” Boşlukları eşleştirin, yeni satır için değil, atın \rve \nbırakın /[\t\f\cK ]/.

Metniniz Unicode ise , yukarıda belirtilen belgeler bölümündeki tablodan bir desen oluşturmak için aşağıdaki alt bölüme benzer kodu kullanın .

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;
}

Diğer uygulamalar

Çift negatif hile, alfabetik karakterleri eşleştirmek için de kullanışlıdır. Bunun \w"kelime karakterleri", alfabetik karakterler , rakam ve alt çizgi ile eşleştiğini unutmayın . Biz çirkin Amerikalılar bazen bunu şöyle derler,

if (/[A-Za-z]+/) { ... }

ancak çift negatif karakter sınıfı yerel ayara saygı duyabilir:

if (/[^\W\d_]+/) { ... }

“Bir kelime karakterini ancak rakam ya da alt çizgiyi değil” bu şekilde ifade etmek biraz opaktır. POSIX karakter sınıfı amacı daha doğrudan iletir

if (/[[:alpha:]]+/) { ... }

veya szbalint'in önerdiği gibi bir Unicode özelliği ile

if (/\p{Letter}+/) { ... }

4
Zeki, ama davranış çok şaşırtıcı ve nasıl daha az garip olduğunu görmüyorum.
Qwertie

7
@Qwertie: Şaşırtıcı olan ne? Ne olduğundan daha az garip?
ysth

9
Mükemmel korkunç.

9
Bu çok iyi. İstendiği gibi, boşlukla (yalnızca bazı boşluk karakterleriyle değil) eşleşirsiniz ve satır besleme karakterini hariç tutarsınız. Çözümünüz, "hangi boşluk karakterlerinin var olduğu" sorusuyla ilgilenmez, olması gerektiği gibi. Tam da aradığım şey buydu. (@Rory tarafından belirtildiği gibi, bir 'satır' de içerebilir \rböylece de maçın gelenler exluding düşünün, Windows üzerinde örneğin: /[^\S\r\n]/)
Timo

1
Bu kesinlikle OP'nin ve bu soruyu araştıran hemen hemen herkesin ihtiyaçlarını karşılayacak (her neyse İngilizce konuşanlar). Ama yine de kötü bir cevap. \hMevcut olduğunda bu çözümü kullanmak için hiçbir mazeret yoktur .
Alan Moore

50

Greg'in cevabında satır başı da içeren bir varyasyon :

/[^\S\r\n]/

Bu normal ifade, /[^\S\n]/hayır ile olduğundan daha güvenlidir \r. Benim gerekçem, Windows'un \r\nyeni satırlar için ve Mac OS 9'un kullanılmasıdır \r. Sen bulmak olası \rolmadan \ngünümüzde, ama bunu bulursak, o ortalama bir şey ama bir yeni satır yapamadı. Dolayısıyla, \ryeni bir satır anlamına gelebileceğinden, bunu da hariç tutmalıyız.


1
+1 Greg'in çözümü metnimi bozdu, seninki iyi çalıştı.
Timo Huovinen

Satır sonları için hala kaç program "\ r" kullandığına şaşırabilirsiniz. Bazen sorunumun dosyanın bunları kullanması olduğunu anlamak biraz zaman aldı. Veya MacRoman karakter kodlamasını kullandığı ...
mivk

2
@Greg ilk "yanlış" değişti ve kredi vermedi gibi görünüyor. Bu yüzden burada oy veriyorum.
Andre Elrico

14

Aşağıdaki normal ifade, beyaz boşluklarla eşleşir, ancak yeni bir satır karakteriyle eşleşmez.

(?:(?!\n)\s)

DEMO

Şaryo iadesi eklemek istiyorsanız \r, |operatöre negatif ileriye baktığınızda ekleyin .

(?:(?![\n\r])\s)

DEMO

+Yakalamayan grubun ardından bir veya daha fazla boşlukla eşleşecek şekilde ekleyin .

(?:(?![\n\r])\s)+

DEMO

Neden insanların [[:blank:]]herhangi bir yatay boşluklar ( boşluklar ve sekmeler ) eşleşen POSIX karakter sınıfı söz başarısız oldu bilmiyorum . Bu POSIX karakter sınıfı, BRE ( Temel Normal İfadeler ), ERE ( Genişletilmiş Düzenli İfade ), PCRE ( Perl Uyumlu Normal İfade ) üzerinde çalışır.

DEMO


Bu en iyi çözüm!
loretoparisi

13

Aradığın şey POSIX blankkarakter sınıfı. Perl'de şöyle denir:

[[:blank:]]

Java'da (etkinleştirmeyi unutmayın UNICODE_CHARACTER_CLASS):

\p{Blank}

Benzeriyle karşılaştırıldığında \h, POSIX blankbirkaç regex motoru tarafından desteklenmektedir ( referans ). Bunun en büyük yararı, tanımının Ek C: Unicode Düzenli İfadelerin Uyumluluk Özellikleri ve Unicode'u destekleyen tüm regex lezzetlerinde standart olarak sabitlenmiş olmasıdır. (Örneğin, Perl'de \hek olarak eklemeyi seçer MONGOLIAN VOWEL SEPARATOR.) Bununla birlikte, lehine bir argüman \hher zaman Unicode karakterleri algılamasıdır (motorlar hangisi üzerinde anlaşmasa bile), POSIX karakter sınıfları genellikle varsayılan ASCII'dir -sadece (Java'da olduğu gibi).

Ancak sorun, Unicode'a bağlı kalmanın bile sorunu% 100 çözmemesi. Unicode'da boşluk olarak kabul edilmeyen aşağıdaki karakterleri göz önünde bulundurun:

  • U + 180E Moğolca Sesli Ayırıcı

  • U + 200B SIFIR GENİŞLİK ALANI

  • U + 200C SIFIR GENİŞLİK BİRLEŞTİRMEYEN

  • U + 200D SIFIR GENİŞLİK BİRLEŞTİRİCİ

  • U + 2060 WORD JOINER

  • U + FEFF SIFIR GENİŞLİK KIRILMAYAN ALAN

    Alındığı https://en.wikipedia.org/wiki/White-space_character

Yukarıda adı geçen Moğolca sesli harf ayırıcısı, muhtemelen iyi bir nedenden dolayı dahil değildir. 200C ve 200D ile birlikte kelimeler (AFAIK) içinde meydana gelir ve bu nedenle diğer tüm boşlukların uyduğu kardinal kuralı ihlal eder: onunla token yapabilirsiniz. Daha çok değiştiriciler gibidirler. Ancak ZERO WIDTH SPACE, WORD JOINERve ZERO WIDTH NON-BREAKING SPACE(bir bayt sırası işareti dışındaki olarak kullanılırsa) kitabımda boşluk kuralı uygun. Bu yüzden onları yatay boşluk karakter sınıfıma dahil ediyorum.

Java dilinde:

static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"

Java derlemesine uygun regexp derleme bayraklarını eklemeniz ve Java 7 veya üstünü çalıştırmanız gerekir. Her durumda, soru Java veya PCRE ile ilgili değildi, bu yüzden hepsi önemsiz.
tchrist

@tchrist Bunu işaret ettiğiniz için teşekkür ederiz. Cevabımı güncelleyeceğim. Yine de cevabımın alakasız olduğuna katılmıyorum. Önemli olmayan perlorijinal sorudaki etikettir.
Aleksandr Dubinsky

1
@AleksandrDubinsky, \ p {Blank} JavaScript'te desteklenmiyor, bu yüzden kesinlikle "tüm normal ifadeler için standart" -1
Valentin Vasilyev

En bilgilendirici. Genel ve eksiksiz bir "yatay boşluk" steno karakter sınıfının olmadığını ve bunun gibi dehşetlerin [\p{Blank}\u200b\u180e]gerekli olduğunu bilmek beni rahatsız ediyor . Kuşkusuz, bir sesli harf ayırıcısının bir boşluk karakteri olarak kabul edilmemesi mantıklıdır , ancak neden sıfır genişlikli alan \sve ve gibi sınıflarda olmamalıdır \p{Blank}.
Timo

Takip: Nedenini açıklamasa da, her ikisinin de 'sınır nötr' olarak kabul edildiğini okudum .
Timo

-4

m/ /gsadece boşluk / /bırakın ve işe yarayacaktır. Veya kullan \S- sekme, yeni satırlar, boşluklar ve benzeri tüm özel karakterlerin yerini alacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.