هل يوجد تعبير عادي متوافق مع Perl لقص المسافات البيضاء من جانبي السلسلة؟
-
06-07-2019 - |
سؤال
هل هناك طريقة للقيام بذلك في سطر واحد؟
$x =~ s/^\s+//;
$x =~ s/\s+$//;
بمعنى آخر، قم بإزالة كافة المسافات البيضاء البادئة والزائدة من السلسلة.
المحلول
$x =~ s/^\s+|\s+$//g;
أو
s/^\s+//, s/\s+$// for $x;
نصائح أخرى
وسؤالي الأول هو ... لماذا؟ أنا لا أرى أي من الحلول التعبير العادي واحد لتكون أكثر قابلية للقراءة من التعبير العادي كنت بدأت. وهم بالتأكيد ليس في أي مكان بالقرب بأسرع.
#!/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*$/
}
},
}
);
ويعطي نتائج على الجهاز الخاص بي من:
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% --
تعديل : لrunrig هو الحق، ولكن مع تغير يذكر. لقد تحديث رمز لنسخ السلسلة قبل التعديل، التي، بطبيعة الحال، ويبطئ الأمور. كما أخذت في الاعتبار اقتراح بريان D فوي في إجابة أخرى لاستخدام سلسلة أطول (على الرغم من مليون بدا وكأنه مبالغة). ومع ذلك، يشير أيضا إلى أن قبل اختيار أسلوب الحيلة، يمكنك معرفة ما هي مثل أطوال سلسلة الخاص بك - وقلل من مزايا خدعة مع سلاسل أقصر. في جميع أطوال لقد اختبرت، على الرغم من انتصارات مزدوجة. وانها لا تزال أسهل على العيون.
وTanktalus معيارا لسلاسل صغيرة جدا، ولكن المشاكل تزداد سوءا كما سلاسل تكبر. في التعليمات البرمجية له، لقد غيرت أعلى حصة:
my $a = 'a' x 1_000_000;
my @x = (
" $a ",
"$a ",
$a,
" $a"
);
وأحصل على هذه النتائج:
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% --
وبما أن سلسلة تكبر، وذلك باستخدام "خدعة" و "ضعف" هي نفسها تقريبا، وحل مشترك أن معظم الناس يذهبون ل، و "واحد" (وأنا من بينهم، لأنني لا يمكن كسر هذه العادة على الرغم من أنا أعرف هذا)، ويبدأ حقا أن تمتص.
وكلما نظرتم معيارا، والتفكير في ما انها أقول لك. لمعرفة ما إذا كنت أفهم ذلك، تغيير البيانات وحاول مرة أخرى. جعل صفائف طويلة، سكالارس كبيرة، وهلم جرا. جعل الحلقات، greps، أو regexes تجد الاشياء في بداية ووسط ونهاية. معرفة ما إذا تطابق نتائج جديدة التنبؤ الخاص بك. معرفة ما هو الاتجاه. لا تحصل أداء أفضل وأفضل، تقترب من الحد، الذروة ثم يبدأ في الانخفاض، أو أي شيء آخر؟
انه ممتع، عليك احضاره!
قرأت مؤخرا مقال يحلل أداء اثني عشر (!) عمليات تنفيذ مختلفة.
على الرغم من أن المقالة تستخدم على وجه التحديد تطبيق JavaScript regex، فإنها تستخدم بناء جملة Perl، لذلك أعتقد أنها مناسبة لهذه المناقشة.
وجدله من هرطقة، لماذا تفعل ذلك على الإطلاق؟ كل الحلول المذكورة أعلاه هي "الصحيح" من حيث أنها تقليم بيضاء من كلا الجانبين من السلسلة في مرور واحد، لكن أيا منها ليس للقراءة بشكل رهيب (نتوقع ربما <لأ href = "https://stackoverflow.com/questions/184590/is -هناك واحد في بيرل المتوافق-العادية-التعبير عن لتقليم بيضاء-من-حد سواء من جانب # 184612 "> هذا واحد ). ما لم يتكون الجمهور لرمز للذات مستوى الخبراء المبرمجون بيرل ينبغي أن يكون كل واحد من المرشحين أعلاه تعليق اصفا ما يفعلونه (وربما فكرة جيدة على أي حال). على النقيض من ذلك، هذين الخطين إنجاز الشيء نفسه دون استخدام lookaheads، البدل، midichlorines أو أي شيء ليست واضحة على الفور إلى مبرمج من الخبرة المعتدلة:
$string =~ s/^\s+//;
$string =~ s/\s+$//;
وهناك (يمكن القول) ضربة الأداء، ولكن طالما أنك لا تشعر بالقلق مع عدد قليل من ميكروثانية في تنفيذ سهولة قراءة وأضاف سوف يستحق كل هذا العناء. IMHO.
وهنا تذهب: $x =~ s/\A\s*(.*?)\s*\z/$1/;
و$ س = ~ ق / (^ \ ق +) | (\ ق + $) // غرام؛
عادةً ما أفعل ذلك على النحو التالي:
($foo) = $foo =~ /^\s*(.*?)\s*$/;
يتم تجميع كل شيء بين المسافات البادئة والمسافات الزائدة وإعادته، حتى أتمكن من تخصيصه لنفس المتغير القديم.
وأو هذا: s/\A\s*|\s*\Z//g
s/^\s*(\S*\S)\s*$/$1/
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
$x =~ s/^\s*(.*?)\s*$/$1/;