Kaşlı ayraçlar arasında dize almak için normal ifade


116

Ne yazık ki, hatırlayabildiğim kadar uzun yıllar boyunca yılda en az bir kez düzenli ifadeyi öğrenmeye çalışmama rağmen, onları çok seyrek kullandığım için her zaman unutuyorum. Bu yıl benim yeni yılım kararım, regex'i tekrar denemek ve öğrenmek değil - Bu yüzden bu yıl beni gözyaşlarından kurtarmak için Stack Overflow'a vereceğim . (Geçen Noel remiksi).

Bu biçimde bir dizge geçirmek ve dizge {getThis}döndürmek istiyorum getThis. Yeni yıl kararıma sadık kalmam için herhangi biri yardımcı olabilir mi?


Stack Overflow ile ilgili sorular:


5
Bu soru, "Gelişmiş Regex-Fu" altındaki Yığın Taşması Normal İfade SSS bölümüne eklenmiştir .
aliteralmind

@Kobi: SSS bir wikidir. Bunu herkes düzenleyebilir. Öyleyse düzenleyin.
aliteralmind

Yanıtlar:


44

Dizeniz her zaman bu biçimde olacaksa, bir normal ifade aşırıdır:

>>> var g='{getThis}';
>>> g.substring(1,g.length-1)
"getThis"

substring(1bir karakterden başlamak (ilk karakterden hemen sonra {) ,g.length-1)anlamına gelir ve karakter dizisi uzunluğu eksi bir olana kadar (ancak dahil değil) karakter almak anlamına gelir. Bu işe yarar çünkü konum sıfır tabanlı, yani g.length-1son konumdur.

Gönderen dışındaki okuyucular için: o takdirde sahip regex, kullanım olmaya /{([^}]*)}/boş dizeleri izin vermek istiyorsanız, ya /{([^}]+)}/küme parantezleri arasında en az bir karakter yokken sadece eşleştirmek istiyorsanız. Yıkmak:

  • /: normal ifade kalıbını başlat
    • {: gerçek bir küme ayracı
      • (: yakalamaya başla
        • [: yakalanacak bir karakter sınıfı tanımlamaya başlayın
          • ^}: "dışında herhangi bir şey }"
        • ]: Tamam, bu bizim tüm sınıf tanımımız
        • *: az önce tanımladığımız sınıfla eşleşen herhangi bir sayıda karakter
      • ): yakalama tamamlandı
    • }: gerçek bir küme ayracı, yakaladığımız şeyi hemen takip etmelidir
  • /: normal ifade desenini sonlandır

7
Alt dize, çalıştığınız dile bağlı olarak değişen şeylerden biridir. Javascript endeksi durmak için alır, PHP istenen son sonucun uzunluğunu alır (negatif olmadıkça, bu durumda kaldırılması gereken karakter sayısı gerekir) , C # yine farklı ... güzel ve kafa karıştırıcı.
jvenema

2
... ve Python'da sadece dilimleme vardır, bu IMO her şeyden daha iyidir: p.
Grant Paul

27
Tatlı, ama bunun nasıl normal bir ifade olduğundan emin değilim. Belki o normal
ifadeyi istiyordu

5
@ baash05, eğer tüm soruyu okursanız, OP normal ifadeyi öğrenmek istemedi, bu yüzden önerdiğiniz akademik alıştırma olduğunu sanmıyorum.
Kev

2
Yapmam gereken -1 soru soran çünkü istediği regex , ben arıyordum regex ama (soru çok kendisini vaat görünüyordu iken) kabul yanıt benim için tamamen işe yaramaz oldu. İlk yorumu okuduktan sonra itiraf etmeliyim ki, bu soruyu önce cevaplasaydım aynı / benzer şekilde cevap verebilirdim ... Yani sonunda +1.
shadyyx

250

Deneyin

/{(.*?)}/

Bu, {ve} arasındaki herhangi bir karakteri eşleştirin, ancak açgözlü olmayın -} ile biten en kısa dizeyi eşleştirin (? Stoplar * açgözlüdür). Parantezler, eşleşen kısmı çıkarmanıza izin verir.

Başka bir yol olurdu

/{([^}]*)}/

Bu, a} karakter dışında herhangi bir karakterle eşleşir (açgözlü olmamanın başka bir yolu)


bu harika, ancak değişken sayıda küme parantez kombinasyonu arasında herhangi bir şeyi eşleştirmek mümkün müdür? Örneğin: "{bu eşleşmeli} bu {bu tür bir kez daha olmalı} ve benzeri {on} olmamalı"? Küme parantezleri içinde olmayan değeri almak istiyorum. Ayrıca: cümle içinde süslü parantez kullanılmaz ve yığınlama olmaz (bu asla gerçekleşmez: "{bazı {metin}}"). Nasıl yapılacağına dair bir fikri olan var mı :)? Teşekkürler! (ps: bu çözüme olumlu oy verdi)
Igor

4
Küme parantezleri arasındaki her şeyi yakalamıyor, küme parantezleri VE küme parantezleri arasındaki her şeyi yakalıyor. YALNIZCA küme parantezlerinin içindekileri yakalamaya nasıl devam edersiniz?
Reality-Torrent

1
Normal ifade ayrıştırıcısı bunların nicelik belirteci olmadığını fark ettiği için buradaki süslü parantezlerden kaçmanıza gerek kalmaması hoşuma gidiyor ... peki, bunu python'da yapıyorum, ancak javascript normal ifadelerinin böyle çalıştığını varsayıyorum too
drevicko

3
gSonuna bir eklemek , onu küresel bir arama yapar. Çalışan bir örneğe
Benjamin

1
@ Reality-Torrent, tüm eşleşmeleri almak için g seçeneğini belirtirsem, ben de küme parantezlerini yakaladığını gördüm. Hem g bayrağına sahip olmak hem de yakalama grubuna izin vermek için Javascript'te string.match yerine bir döngüde Regex.exec kullanmalıyım. Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
frank

150
/\{([^}]+)\}/

/        - delimiter
\{       - opening literal brace escaped because it is a special character used for quantifiers eg {2,3}
(        - start capturing
[^}]     - character class consisting of
    ^    - not
    }    - a closing brace (no escaping necessary because special characters in a character class are different)
+        - one or more of the character class
)        - end capturing
\}       - the closing literal brace
/        - delimiter

@meouw sa = s.split ("/ \ {([^}] +) \} /"); derleme hatası verir. geçersiz tekrar, geçersiz kaçış karakteri.
likejudo

@Anil, normal bir ifade yerine bölünmüş argümanınız olarak bir dizeyi kullanıyor görünüyorsunuz. Ne yapmaya çalışıyorsun?
meouw

30

Bunu dene:

/[^{\}]+(?=})/g

Örneğin

Welcome to RegExr v2.1 by #{gskinner.com},  #{ssd.sd} hosted by Media Temple!

dönecektir gskinner.com, ssd.sd.


1
Harika, neden \}ilk blokta kullandığınızı açıklayabilir misiniz ?
Uzair Ali

1
Güzel bir şey, ama bu, başlasa }bile , biten herhangi bir grupla eşleşecek {.
Ahmad Ibrahim

1
Bu gerçekten işe yarayan tek doğru cevaptır.
pldg

Açıklama: [^ \ {\}] + küme ayracı olmayan herhangi bir şeyle eşleşirken, önden okuma iddiası (? =}) Yalnızca küme ayracından önceki bölümleri geçmeyi sağlar. / ... / g ile yalnızca birincisini değil, tüm olayları elde ederiz.
0 -_- 0

20

İşte javascript değiştirme kullanarak basit bir çözüm

var st = '{getThis}';

st = st.replace(/\{|\}/gi,''); // "getThis"

Yukarıda kabul edilen yanıtın işaret ettiği gibi, orijinal sorun alt dizeyle kolayca çözülür, ancak değiştirme kullanımı daha karmaşık kullanım durumlarını çözebilir

"Randomstring999 [alanadı]" gibi bir dizeniz varsa, alan adını almak için biraz farklı bir kalıp kullanırsınız

var nameAttr = "randomstring999[fieldname]";

var justName = nameAttr.replace(/.*\[|\]/gi,''); // "fieldname"

15

Bu, Textmate'te çalışır ve küme parantezleri arasındaki bir CSS dosyasındaki her şeyi eşleştirir.

\{(\s*?.*?)*?\}

selector {. . matches here including white space. . .}

İçeriği daha fazla geri döndürebilmek istiyorsanız, hepsini birden fazla parantez içine sarın:

\{((\s*?.*?)*?)\}

ve içeriğe $ 1 üzerinden erişebilirsiniz.

Bu aynı zamanda işlevler için de işe yarar, ancak bunu iç içe kıvrık parantezlerle test etmedim.


14

Normal ifade önden bakma ve arkaya bakma kullanmak istiyorsunuz. Bu size yalnızca küme parantezlerinin içindekileri verecektir:

(?<=\{)(.*?)(?=\})

Yukarıdaki süslü parantezlerden kaçan bir ters eğik çizgi olmalıdır. Benim sunumumda ellerinden alındı.
Robert Cesaric

1
Teşekkürler, bu bugün bana yardımcı oldu.
ProfessionalAmateur

bu yöntemin herhangi bir dezavantajı var mı?
Somatik

5
@ Somatik — evet, negatif bakış ve arkalar ECMAScript'te desteklenmez.
RobG

Not: Bu örnek Java'da çalışır. Tüm küme parantezlerindeki tüm değerleri döndürür.
Multiplexor

14

Bunu dene

let path = "/{id}/{name}/{age}";
const paramsPattern = /[^{\}]+(?=})/g;
let extractParams = path.match(paramsPattern);
console.log("extractParams", extractParams) // prints all the names between {} = ["id", "name", "age"]

1
Tam olarak istediğim şey :) bu, sonucu diş telleri olmadan döndürecek, diğer çözümler de onunla geri dönecek
Al-Mothafar

Mükemmel, buradaki en iyi cevap.
michal.jakubeczy

4

Küme parantezleri içine alınmış dizge dizilerini almak için normal ifade, yalnızca ilk geçtiği yeri bulmaktan ziyade dizede bulunur.

 /\{([^}]+)\}/gm 

4

Diğer cevaplara baktım ve onlardan hayati bir mantık eksik görünüyor. yani, iki CONSECUTIVE parantez arasındaki her şeyi seçin, ancak parantezleri DEĞİL

işte cevabım

\{([^{}]+)\}

3
var re = /{(.*)}/;
var m = "{helloworld}".match(re);
if (m != null)
    console.log(m[0].replace(re, '$1'));

.replace(/.*{(.*)}.*/, '$1')Normal ifade eşleşmezse maalesef daha basit olan dizenin tamamını döndürür. Yukarıdaki kod parçacığı bir eşleşmeyi daha kolay tespit edebilir.



2

Bu normal ifade özyinelemesini, aradaki her şeyi, hatta bir başkasını {}(bir JSON metni gibi) eşleştirmek için kullanabilirsiniz :

\{([^()]|())*\}

Güzel, ancak bu yalnızca iç içe geçmiş diş tellerinin içindeki içeriği yakalıyor
Dominic

içerik () içeriyorsa yakalanmıyor
Mert Mertce

1

Bu bile birisinin problemini çözmeye çalışırken bana yardımcı oluyor.

İçeriği {}, gibi bir kalıba sahip küme parantezlerinin ( ) içine bölün {'day': 1, 'count': 100}.

Örneğin:

#include <iostream> 
#include <regex> 
#include<string> 
using namespace std; 

int main() 
{ 
    //string to be searched
    string s = "{'day': 1, 'count': 100}, {'day': 2, 'count': 100}";

    // regex expression for pattern to be searched 
    regex e ("\\{[a-z':, 0-9]+\\}");
    regex_token_iterator<string::iterator> rend;

    regex_token_iterator<string::iterator> a ( s.begin(), s.end(), e );
    while (a!=rend) cout << " [" << *a++ << "]";
    cout << endl;

    return 0; 
}

Çıktı:

[{'day': 1, 'count': 100}] [{'day': 2, 'count': 100}]
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.