Bunu bir satırda yapmanın bir yolu var mı? Başka bir deyişle, tüm ön ve arka boşlukları bir dizeden kaldırın. İşteBir dizenin her iki tarafındaki boşlukları kesmek için Perl uyumlu bir düzenli ifade var mı?
cevap
$x =~ s/^\s+|\s+$//g;
veya
s/^\s+//, s/\s+$// for $x;
Seçenek 2: Bu iyi bir numara, ama gerçekten şu soruya cevap vermiyor: D – ephemient
Bu soruya nasıl cevap vermiyor? Tek regex'in sıraya koyma performansı olmadan iki taraftan da kırpıyor. –
s/^ \ s * (. *?) \ S */\ 1 /; –
gitmek: $x =~ s/\A\s*(.*?)\s*\z/$1/;
$ x = ~ s/(^ \ s +) | (\ s + $) // g;
ben her zaman böyle yaparım .. çok kolay görünüyor. – Kip
evet, ve ne anlama geldiğini söyler - beyaz alanın yerini değiştirin VEYA beyaz boşluğu biten hiçbir şeyle küresel olarak değiştirin. –
Yakalama parantezleri kullanılmaz veya ihtiyaç duymaz - genellikle bunları gruplayıcı parantezler (?: ...) ile değiştirebilirsiniz, ancak bu durumda öncelik güzel bir şekilde çalışır ve parantezleri tamamen kaldırabilirsiniz. – ephemient
$x =~ s/^\s*(.*?)\s*$/$1/;
Değiştirme dizesinde $ 1 yerine \ 1 kullanılması Perl'de önerilmez, perldoc perlre'da "$ 1 üzerinde uyarı 1'e bakın" konusuna bakın. – ephemient
Niceleyiciler açgözlü olduğundan, \ s + ile eşleştikten sonra [^ \ s] gibi bir şey söylemeniz gerekmez. Ayrıca, [^ \ s] yerine, sadece \ S diyebilirsiniz. Büyük harfli sürümler tamamlanmış karakter sınıfıdır. :) –
brian: Evet, ama sadece ben yaparsam. * Ungreedy. – Lev
Ya da bu: s/\A\s*|\s*\Z//g
Benim ilk soru ... neden? Tek regexp çözümlerinden hiçbirini, başladığınız regexp'den daha okunabilir olacak şekilde görmüyorum. Ve hızlı bir şekilde yakın bir yerde değiller.
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(:all);
my $a = 'a' x 1_000;
my @x = (
" $a ",
"$a ",
$a,
" $a"
);
cmpthese(-5,
{
single => sub {
for my $s (@x)
{
my $x = $s;
$x =~ s/^\s+|\s+$//g;
}
},
double => sub {
for my $s (@x)
{
my $x = $s;
$x =~ s/^\s+//;
$x =~ s/\s+$//;
}
},
trick => sub {
for my $s (@x)
{
my $x = $s;
s/^\s+//, s/\s+$// for $x;
}
},
capture => sub {
for my $s (@x)
{
my $x = $s;
$x =~ s/\A\s*(.*?)\s*\z/$1/
}
},
kramercap => sub {
for my $s (@x)
{
my $x = $s;
($x) = $x =~ /^\s*(.*?)\s*$/
}
},
}
);
benim makinede sonuçlar verir:
Rate single capture kramercap trick double single 2541/s -- -12% -13% -96% -96% capture 2902/s 14% -- -0% -95% -96% kramercap 2911/s 15% 0% -- -95% -96% trick 60381/s 2276% 1981% 1974% -- -7% double 65162/s 2464% 2145% 2138% 8% --
Düzenleme: Runrig haklı, ama biraz değişime. Değişiklikten önce dizeyi kopyalamak için kodu güncelledim, ki bu da bazı şeyleri yavaşlatıyor. Ben de daha uzun bir dize kullanmak için başka bir cevapta Brian d düşündüren öneri (bir milyon gibi overkill gibi görünüyordu) dikkate aldı. Bununla birlikte, bu aynı zamanda, hile stilini seçmeden önce, dize uzunluklarının neye benzediğini anlamanızı önerir - hilenin avantajları kısa dizelerle azalır. Yine de test ettiğim tüm uzunluklarda, çift kazanır. Ve yine de gözlerde daha kolay.
Perl'de bunu yaptığını varsayıyorsunuz ve bu durum böyle olmayabilir. "Perl uyumlu" her zaman benim için kırmızı bayraklar yükseltir. –
Doğru - hem perl hem de pcre etiketlerini görmek biraz kafa karıştırıcı ... – Tanktalus
Tüm "testler" inizde ilk iterasyonda @x değişecektir. Yani hiçbiri düşündüğünüzü test etmiyor. Subs'larınızda @x kopyalamanız gerekiyor. Ve çift çözümde, bir for döngüsüne sarmayın, sadece "for @x" kullanın. – runrig
Heretik olarak tartışmak, neden hiç yapmıyorsunuz? Yukarıdaki çözümlerin hepsi, dizgenin her iki tarafındaki boşlukları tek geçişte kırptıkları için "doğru" dır, ancak hiçbiri korkunç şekilde okunamaz (belki de this one). Kodunuzun izleyici kitlesi uzman seviyesindeki Perl kodlayıcılarından oluşmadıkça, yukarıdaki adayların her birinin ne yaptıklarını açıklayan bir yorumu olmalıdır (muhtemelen iyi bir fikir). Buna karşılık, bu iki hat ılımlı deneyim programcı hemen açık değildir lookaheads, joker, midichlorines ya da bir şey kullanmadan aynı şeyi başarmak:
$string =~ s/^\s+//;
$string =~ s/\s+$//;
(tartışmalı) bir performans isabet, ancak bulunmamaktadır yürütme sırasında birkaç mikrosaniye ile ilgilenmediğiniz sürece eklenen okunabilirlik buna değer olacaktır. BENİM NACİZANE FİKRİME GÖRE.
Performans vuruldu mu? Bunu kim tartışabilir? Listelenen diğer çözümlerden iki kat daha hızlı. – Tanktalus
Yeterince adil, kodu kıyaslamadım çünkü (çok) geç öğle yemeği için kapıdan çıkmak istedim. Performans isabetinin olmadığını bilmek güzel. – Logan
Perl uzmanı? Öğrenme Perl'imdeki insanlar, tüm bu çözümleri, ikinci günün sonunda anlayacaktır. –
Komik bunu yukarı getirmelisiniz!
Geçenlerde an article analyzing the performance of twelve (!) different trim implementations okuyun.makalesinde özel JavaScript regex uygulaması kullanmasına rağmen
, bu Perl sözdizimi kullanır, bu yüzden bu tartışmaya yerinde olduğunu düşünüyorum.Tanktalus çok küçük dizeleri için bir kıyaslamayı gösterir, ancak dizeleri büyük olsun gibi sorunlar kötüleşir.
my $a = 'a' x 1_000_000;
my @x = (
" $a ",
"$a ",
$a,
" $a"
);
Ben bu sonuçları elde: Onun kodda, üst kısmı değişti dize "hile" ve "çifte" neredeyse aynıdır ve kullanarak büyür
Rate single capture trick double
single 2.09/s -- -12% -98% -98%
capture 2.37/s 13% -- -98% -98%
trick 96.0/s 4491% 3948% -- -0%
double 96.4/s 4512% 3967% 0% --
olarak Çoğu insanın gittiği ortak çözüm, “bekar” (benim de dahil olmak üzere, bunu bildiğim halde bu alışkanlığı kıramayacağım), gerçekten de emmeye başlar.
Bir ölçüte her baktığınız zaman, size ne söylediğini düşünün. Anladığınızı anlamak için verileri değiştirin ve tekrar deneyin. Diziler uzun, skaler büyük, vb. Döngüleri, grevleri veya normal ifadeleri başlangıç, orta ve sonda şeyler bul. Yeni sonuçların tahmininize uygun olup olmadığını görün. Eğilimin ne olduğunu anlamaya. Performans daha iyi ve daha iyi olur mu, bir limite yaklaşır, zirve sonra da düşmeye başlar, ya da başka bir şey?
Genellikle böyle yapmak: öncü alanlarda ve izleyen boşlukları arasındaki
($foo) = $foo =~ /^\s*(.*?)\s*$/;
Her şey gruplandırılmış ve döndü, bu yüzden aynı eski değişkene atayabilirsiniz edilir.
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
"Döşeme", bir dizgenin her iki tarafındaki beyaz geçişin kaldırılması için normal addır. Yapabilirsin: $ title = ~ s/remove/trim/ – Kip
"pcre" etiketini kaldırıyorum çünkü C regex kütüphanesinin adı (PHP'nin preg fonksiyonlarını çalıştıran), ve açıkçası bu şekilde kullanılmıyor. İşte. –