Normal bir ifadedeki herhangi bir karakteri birden çok satırda nasıl eşleştirebilirim?


359

Örneğin, bu normal ifade

(.*)<FooBar>

eşleşecek:

abcde<FooBar>

Ancak birden çok satıra eşleşmesini nasıl sağlayabilirim?

abcde
fghij<FooBar>

1
Netleştirmek için; Başlangıçta Eclipse kullanarak birden fazla dosyada bul ve değiştir kullanıyordum. Aşağıdaki cevaplar tarafından keşfettiğim şey, benim sorunum regex desen değil aracı oldu.
andyuk

2
Bayrağınız "eclipse" kaldırılmalıdır, çünkü bir eclipse çözümü arayan biri bu soruyu (benim yaptığım gibi) bulacaktır ve sonra kabul edilen bir eclipse çözümü bulacaktır.
acme

2
Şimdi bunu arama motorunda buluyorum çünkü tutulmadan bahsedildi. Ah dehşet.
Brian Olsen

Yanıtlar:


240

Dile bağlıdır, ancak normal ifadeye ekleyebileceğiniz bir değiştirici olmalıdır. PHP'de:

/(.*)<FooBar>/s

Sondaki s , noktanın yeni satırlar dahil tüm karakterlerle eşleşmesine neden olur .


ve ya tüm karakterleri değil, sadece yeni bir satır isteseydim ?
Grace

3
@Grace: kullanım \ n satırbaşı maç için
Jeremy Ruten

5
En azından Chrome / V8'de s işareti (şimdi?) Geçersiz. Bunun yerine, dönem eşleştirici yerine / ([\ s \ S] *) <FooBar> / karakter sınıfını (eşleşme alanı ve boşluk olmayan] kullanın. Daha fazla bilgi için diğer yanıtlara bakın.
Allen

8
@Allen - JavaScript sdeğiştiriciyi desteklemiyor . Bunun yerine, [^]*aynı etkiyi yapın.
Derek 朕 會 功夫

1
Ruby'de mdeğiştiriciyi kullanın
Ryan Buckley

358

Bunu dene:

((.|\n)*)<FooBar>

Temelde sıfır veya daha fazla kez tekrarlanan "herhangi bir karakter veya yeni satır" yazıyor.


5
Bu, kullandığınız dile ve / veya araca bağlıdır. Lütfen ne kullandığınızı bize bildirin, örneğin Perl, PHP, CF, C #, sed, awk, vs.
Ben Doom

39
Hat uçlarınıza bağlı olarak ihtiyacınız olabilir((.|\n|\r)*)<FooBar>
Potherca

3
Eclipse kullandığını söyledi. Bence bu doğru çözüm. Aynı sorunum var ve bu çözüldü.
Danubian Sailor

4
Doğru - soru tutulma ile ilgilidir ve etiketler de öyle. Ancak kabul edilen çözüm bir PHP çözümüdür. Seninki kabul edilen çözüm olmalı ...
acme

16
Bu, çoklu satır girişini eşleştirmek için en kötü regex'tir. Lütfen Esnek Arama özelliğini kullanmadığınız sürece asla kullanmayın. [\s\S]*Veya tuşunu kullanın (?s).*.
Wiktor Stribiżew

90

Soru şu, .örüntü herhangi bir karakterle eşleşebilir mi? Cevap motordan motora değişir. Temel fark, desenin bir POSIX veya POSIX olmayan normal ifade kütüphanesi tarafından kullanılıp kullanılmadığıdır.

Hakkında özel not : normal ifadeler olarak kabul edilmezler, ancak .POSIX tabanlı motorlarla aynı şekilde herhangi bir karakterle eşleşirler.

Hakkında başka bir not ve : .varsayılan olarak herhangi bir karakterle eşleşir ( demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');( tokensbir abcde\n fghijöğe içerir ).

Ayrıca, tümünde 'nin normal ifadesi, varsayılan olarak nokta satır sonlarıyla eşleşir. Boost'un ECMAScript dilbilgisi, bunu regex_constants::no_mod_m( kaynak ) ile kapatmanıza izin verir .

Gelince (POSIX tabanlıdır) nseçeneğini ( demo ) kullanın :select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

POSIX tabanlı motorlar :

Yalnızca .satır sonlarıyla eşleşiyor, değiştirici kullanmaya gerek yok, bkz.( demo ).

( demo ),( demo ),(TRE, taban R varsayılan motoru yok perl=TRUE, taban R için perl=TRUEveya stringr / stringi desenleri için (?s)satır içi değiştiriciyi kullanın ) ( demo ) da .aynı şekilde davranın .

Ancak , POSIX tabanlı araçların çoğu girişi satır satır işler. Bu nedenle, .yalnızca kapsamda olmadıkları için satır sonlarıyla eşleşmez. Bunu nasıl geçersiz kılacağınıza dair bazı örnekler:

  • - Birden çok geçici çözüm vardır, en kesin ama çok güvenli olmayan sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'( H;1h;$!d;x;dosyayı belleğe kaydırır). Tüm satırların dahil edilmesi gerekiyorsa, sed '/start_pattern/,/end_pattern/d' file(başlangıçtan kaldırma eşleşen satırlar dahil olarak sona erecektir) veya sed '/start_pattern/,/end_pattern/{{//!d;};}' file(eşleşen satırlar hariç) düşünülebilir.
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"( -0tüm dosyayı hafızaya alır, -pverilen komut dosyasını uyguladıktan sonra dosyayı yazdırır -e). Kullanmanın -000pedosyayı bozacağını ve Perl'in \n\nkayıt ayırıcı olarak ardışık satırları ( ) kullandığını 'paragraf modunu' etkinleştireceğini unutmayın .
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file. Burada zdosya kaydırmayı (?s)etkinleştirir, .desen için DOTALL modunu (?i)etkinleştirir, büyük / küçük harf duyarsız modu etkinleştirir, \Kşimdiye kadar eşleşen metni atlar, *?tembel bir niceleyicidir, (?=<Foobar>)önceki konumla eşleşir <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file( Mburada dosya kaydırmayı etkinleştirir). Not pcregrep, Mac OS grepkullanıcıları için iyi bir çözümdür .

Demolara bakın .

POSIX tabanlı olmayan motorlar :

  • - Kullanım sdeğiştirici PCRE_DOTALL değiştirici : preg_match('~(.*)<Foobar>~s', $s, $m)( demo )
  • - RegexOptions.SinglelineBayrak ( demo ) kullanın :
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    -var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - (?s)Satır içi seçeneğini kullan :$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - sDeğiştirici kullanın (veya (?s)başlangıçtaki satır içi sürümü) ( demo ):/(.*)<FooBar>/s
  • - re.DOTALL(veya re.S) bayrakları veya (?s)satır içi değiştirici ( demo ) kullanın: m = re.search(r"(.*)<FooBar>", s, flags=re.S)(ve sonra if m:, print(m.group(1)))
  • - Pattern.DOTALLDeğiştirici (veya satır içi (?s)bayrak) ( demo ) kullanın:Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - (?s)Model içi değiştirici kullanın ( demo ):regex = /(?s)(.*)<FooBar>/
  • - (?s)Değiştirici ( demo ) kullanın :"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • - Kullanın [^]veya geçici çözümler [\d\D]/ [\w\W]/ [\s\S]( demo ) kullanın:s.match(/([\s\S]*)<FooBar>/)[1]
  • ( std::regex) [\s\S]Veya JS geçici çözümlerini kullanın ( demo ):regex rex(R"(([\s\S]*)<FooBar>)");
  • - JavaScript ile aynı yaklaşımı kullanın ([\s\S]*)<Foobar>,. ( NOT : MultiLinemalı RegExpnesnesi bazen yanlışlıkla izin seçenek olduğu düşünülmektedir ., aslında, sadece değiştirirken, satır sonları maç ^ve $başlasın maç davranışı / bitiş çizgileri yerine dizeleri aynı JS regex olduğu gibi ) davranış.)

  • - /m MULTILINE değiştiricisini ( demo ) kullanın :s[/(.*)<Foobar>/m, 1]

  • - Base R PCRE normal ifadeleri - kullanım (?s): regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]( demo )
  • - ICU regex motoruyla çalışan in stringr/ stringiregex işlevleri, ayrıca (?s)şunları kullanın : stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]( demo )
  • - (?s)Başlangıçta satır içi değiştiriciyi kullanın ( demo ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - Satır içi değiştiriciyi kalıba aktarın dotMatchesLineSeparatorsveya (daha kolay) kullanın (?s):let rx = "(?s)(.*)<Foobar>"
  • - Swift ile aynı, (?s)en kolay çalışır, ancak seçenek nasıl kullanılabilir :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - (?s)Değiştirici ( demo ) kullanın : "(?s)(.*)<Foobar>"(Google E-Tablolarda, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

NOTLAR(?s) :

POSIX olmayan çoğu motorda, (?s)satır .kesmelerini eşleştirmek için satır içi değiştirici (veya katıştırılmış bayrak seçeneği) kullanılabilir .

Desenin başına yerleştirilirse, desendeki (?s)herkesin davranışını değiştirir .. Eğer (?s)başından sonra bir yere yerleştirilir, yalnızca .onun sağındaki yer aldığını etkilenecektir sürece bu Python geçirilen bir kalıptır re. Python'da re, (?s)konumdan bağımsız olarak , tüm desen .etkilenir. (?s)Etkisi kullanılarak durdurulur (?-s). Değiştirilmiş bir grup, yalnızca normal ifade düzeninin belirli bir aralığını etkilemek için kullanılabilir (örneğin Delim1(?s:.*?)\nDelim2.*, ilk .*?satırları yeni satırlar arasında ve ikinci satır .*yalnızca satırın geri kalanıyla eşleşir).

POSIX notu :

POSIX olmayan normal ifade motorlarında, herhangi bir karakterle eşleşmek için [\s\S]/ [\d\D]/ [\w\W]konstruktlar kullanılabilir.

POSIX'te, [\s\S]regex kaçış dizileri köşeli ayraç ifadelerinde desteklenmediği için hiçbir karakterle (JavaScript veya POSIX olmayan herhangi bir motorda olduğu gibi) eşleşmiyor. [\s\S], tek bir karakterle eşleşen köşeli ayraç ifadeleri olarak ayrıştırılır \veya sveya S.


5
Bu mükemmel genel bakışa profil sayfanızdan veya bir şeyden (+1) bağlantı vermelisiniz.
Ocak

1
Bunu boost öğesine eklemek isteyebilirsiniz : regex_constants ad alanında, flag_type_'s: perl = ECMAScript = JavaScript = JScript = :: boost :: regbase :: normal = 0, Perl varsayılanıdır. Programcılar bunu #define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_myansıtması için normal regex bayrakları için bir temel bayrak tanımı belirleyeceklerdir. Ve hakem her zaman satır içi değiştiricilerdir. Nerede (?-sm)(?s).*sıfırlanır.

1
Ayrıca bash için de ekleyebilirsiniz?
Pasupathi Rajamanickam

2
@PasupathiRajamanickam Bash bir POSIX normal ifade motoru kullanır, .orada herhangi bir karakterle eşleşir (satır sonları dahil). Bu çevrimiçi Bash demosuna bakın .
Wiktor Stribiżew

1
Siz sallayın - bu şimdiye kadar gördüğüm (nispeten) karmaşık regexp'lerin en kapsamlı mini öğreticisidir. Cevabınızın kabul edilen cevap olmasını hak ediyorsunuz! Şeref ve Gocevaba dahil etmek için ekstra oy !
Gwyneth Llewelyn

68

Eclipse aramasını kullanıyorsanız, '.' Yapmak için "DOTALL" seçeneğini etkinleştirebilirsiniz. satır sınırlayıcılar dahil herhangi bir karakterle eşleşir: arama dizenizin başına "(? s)" eklemeniz yeterlidir. Misal:

(?s).*<FooBar>

1
Hiçbir yerde değil, yalnızca satır içi değiştiricileri destekleyen normal ifade tatlarında ve kesinlikle Ruby'de değil nerede (?s)=>(?m)
Wiktor Stribiżew

Bash için bir şey var mı?
Pasupathi Rajamanickam

38

Birçok normal ifade lehçelerinde, /[\S\s]*<Foobar>/tam olarak istediğinizi yaparsınız. Kaynak


2
Bu bağlantıdan: "JavaScript ve VBScript'te nokta eşleme satırı sonu karakterleri oluşturma seçeneği yoktur. Bu dillerde, herhangi bir karakteri eşleştirmek için [\ s \ S] gibi bir karakter sınıfı kullanabilirsiniz." Onun yerine . bunun yerine [\ s \ S] kullanın (boşlukları ve boşluk olmayanları eşleştir).
Allen

32

([\s\S]*)<FooBar>

Nokta, yeni satırlar (\ r \ n) dışındaki tüm öğelerle eşleşir. Bu yüzden TÜM karakterlerle eşleşecek \ s \ S kullanın.


Objective-C kullanıyorsanız, bu sorunu çözmek [text rangeOfString:regEx options:NSRegularExpressionSearch]. Teşekkürler!
J. Costa

1
Bu intelliJ's bul ve değiştir regex çalışır, teşekkürler.
barclay

Bu çalışıyor. Ama bunun ilk oluşumu olmalı<FooBar>
Özkan

18

In Yakut ' m' seçeneğini kullanabilirsiniz (çok satırlı):

/YOUR_REGEXP/m

Daha fazla bilgi için ruby-doc.org adresindeki Regexp belgelerine bakın .


13

biz de kullanabiliriz

(.*?\n)*?

açgözlü olmadan newline dahil her şeyi eşleştirmek

Bu, yeni satırı isteğe bağlı yapacaktır

(.*?|\n)*?

8

"."normalde satır kesmeleriyle eşleşmez. Çoğu regex motoru, yeni satırlarla eşleşmesi için S-flag ( DOTALLve olarak da adlandırılır SINGLELINE) eklemenizi sağlar ".". Bu başarısız olursa, böyle bir şey yapabilirsiniz [\S\s].


8

Eclipse için aşağıdaki ifadeyi çalıştı:

foo

jadajada Bar "

Düzenli ifade:

Foo[\S\s]{1,10}.*Bar*

5
/(.*)<FooBar>/s

s, Nokta (.) öğesinin satır başı ile eşleşmesine neden olur


Bunun geçersiz (Chrome) olduğu anlaşılıyor: text.match (/ a / s) Sözdizimi Hatası: RegExp yapıcısına geçersiz bayraklar sağlandı
Allen

Çünkü JavaScript RegEx motorlarında desteklenmez. sBayraklar, PCRE'nin var (Perl ve PHP mevcuttur) en eksiksiz motoru. PCRE'de 10 bayrak (ve diğer birçok özellik) bulunurken, JavaScript'te yalnızca 3 bayrak ( gmi) bulunur.
Morgan Touverey Quilling

4

Java tabanlı düzenli ifadede şunları kullanabilirsiniz: [\s\S]


1
Bunlar ters eğik çizgi olmamalı mı?
Paul Draper

Düzenli İfadenin sonuna gidiyorlar, içeride değil. Örnek: / blah / s
RandomInsano

Sanırım JavaScript değil, JavaScript mi? sJava'da desene sadece bayrak ekleyebileceğiniz ve JavaScript'in sbayrağı olmadığı için .
3limin4t0r

3

(.|\n)*Bunun (örneğin) [\s\S]*(dilinizin regex'leri bu tür kaçışları destekliyorsa) ve yapan değiştiricinin nasıl belirtileceğini bulmaktan daha az etkili olabileceğini unutmayın . ayrıca yeni satırlarla eşleşir. Veya POSIXy gibi alternatiflerle gidebilirsiniz [[:space:][:^space:]]*.


3

RegexOptions.Singleline kullanın, anlamını değiştirir. yeni satırlar eklemek

Regex.Replace (içerik, searchText, replaceText, RegexOptions.Singleline);



1

Diller içinde kullanım bağlamında, düzenli ifadeler satırlara değil, dizelere göre hareket eder. Bu nedenle, giriş dizesinin birden çok satırı olduğunu varsayarak normal ifadeyi normal şekilde kullanabilmeniz gerekir.

Bu durumda, "<FooBar>" mevcut olduğundan, verilen normal ifade tüm dizeyle eşleşecektir. Normal ifade uygulamasının özelliklerine bağlı olarak, 1 $ değeri ("(. *)" Den elde edilir) "fghij" veya "abcde \ nfghij" olur. Diğerlerinin söylediği gibi, bazı uygulamalar "." size yeni bir seçenek sunacak.

Satır tabanlı düzenli ifade kullanımı genellikle egrep gibi komut satırı şeyler içindir.


1

Aynı sorunu yaşadım ve muhtemelen en iyi şekilde çözemedim ama işe yarıyor. Gerçek maçımı yapmadan önce tüm satır sonlarını değiştirdim:

mystring= Regex.Replace(mystring, "\r\n", "")

HTML'yi manipüle ediyorum, bu nedenle satır sonları benim için gerçekten önemli değil.

Yukarıdaki tüm önerileri şanssız denedim, .Net 3.5 FYI kullanıyorum


Ben de .NET kullanıyorum ve (\s|\S)benim için hile yapmak gibi görünüyor!
Vamshi Krishna

@VamshiKrishna .NET'te, herhangi bir karakterle eşleştirmek (?s)için kullanın .. (\s|\S)Performansı yavaşlatacak şekilde kullanmayın .
Wiktor Stribiżew

1

Javascript'te satır sonları dahil olmak üzere sıfır ila sonsuz karakter aramak için [^] * kullanabilirsiniz.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>


0

genellikle. yeni satırlarla eşleşmediğinden, deneyin((.|\n)*)<foobar>


3
Hayır, yapma. Hat ayırıcılar dahil herhangi bir şeyle eşleşmeniz gerekiyorsa DOTALL (aka / s veya SingleLine) değiştiricisini kullanın. (. | \ N) kesmek, normal ifadeyi daha az verimli hale getirmekle kalmaz, doğru bile değildir. En azından \ r (satır başı) ve \ n (satır besleme) ile eşleşmelidir. Nadiren de olsa başka satır ayırıcı karakterler de vardır. Ancak DOTALL bayrağını kullanırsanız, onlar için endişelenmenize gerek yoktur.
Alan Moore

1
\ R, Eclipse'deki yeni satırlar için platformdan bağımsız eşleşmedir.
opyate

@opyate Bu küçük cevher inanılmaz derecede faydalı olduğu için bunu bir cevap olarak göndermelisiniz.
jeckhart

Bunun yerine bunu deneyebilirsiniz. İç braketlerle eşleşmeyecek ve isteğe bağlı olarak da düşünülecektir \r:((?:.|\r?\n)*)<foobar>
ssc-hrep3

0

Java'daki belirli bir blokla eşleşmek istedim

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

Eğer regExp kullanırsam

if \(isTrue(.|\n)*}

yöntem bloğunun kapanış ayracı dahil, bu yüzden kullandım

if \(!isTrue([^}.]|\n)*}

kapanış ayracı joker karakter eşleşmesinden hariç tutulmalıdır.


0

Genellikle, bir alt dizeyi, alt dizeden önceki satırlara yayılmış birkaç anahtar kelimeyle değiştirmeliyiz. Bir xml öğesini düşünün:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

81 diyelim ki 40 diyelim başka bir değerle değiştirmek istediğimizi varsayalım. Önce tanımlayın .UID.21..UID., daha sonraya \nkadar olan tüm karakterleri atlayın .PercentCompleted.. Normal ifade deseni ve değiştirme belirtimi şunlardır:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

Alt grup (.|\n)muhtemelen eksik gruptur $3. Biz tarafından dışı yakalama yaparsanız (?:.|\n)o zaman $3olduğunu (<PercentComplete>). Böylece desen ve replaceSpecayrıca olabilir:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

ve değiştirme daha önce olduğu gibi düzgün çalışır.


0

Tipik olarak Powershell'de ardışık üç satır aramak şöyle görünür:

$file = get-content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # both

$file -match $pattern

# output
True

Tuhaf bir şekilde, bu komut isteminde unix metni olurdu, ancak bir dosyadaki Windows metni:

$pattern = 'lineone
linetwo
linethree
'

İşte satır sonlarını yazdırmanın bir yolu:

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# output
lineone\nlinetwo\nlinethree\n

-2

seçenek 1

Bunun bir yolu sbayrağı kullanmaktır (tıpkı kabul edilen cevap gibi):

/(.*)<FooBar>/s

Demo 1

seçenek 2

İkinci yol, m(çok satırlı) bayrağı ve aşağıdaki kalıplardan herhangi birini kullanmaktır:

/([\s\S]*)<FooBar>/m

veya

/([\d\D]*)<FooBar>/m

veya

/([\w\W]*)<FooBar>/m

Demo 2

RegEx Devresi

jex.im düzenli ifadeleri görselleştirir:

resim açıklamasını buraya girin

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.