Gibt es einen perl-kompatiblen regulären Ausdruck, um die Whitespace von beiden Seiten einer Schnur zu schneiden?

StackOverflow https://stackoverflow.com/questions/184590

  •  06-07-2019
  •  | 
  •  

Frage

Gibt es eine Möglichkeit, dies in einer Zeile zu tun?

$x =~ s/^\s+//;
$x =~ s/\s+$//;

Mit anderen Worten, entfernen Sie alle führenden und nachlaufenden Whitespace von einer Saite.

War es hilfreich?

Lösung

$x =~ s/^\s+|\s+$//g;

oder

s/^\s+//, s/\s+$// for $x;

Andere Tipps

Meine erste Frage ist ... Warum? Ich sehe keine der Single-Regexp-Lösungen als lesbarer als das Regexp, mit dem Sie begonnen haben. Und sie sind sicher nicht so schnell.

#!/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*$/
                 }
             },
         }
        );

gibt Ergebnisse auf meiner Maschine von:

             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%        --

Bearbeiten: Runrig hat Recht, aber wenig Veränderung. Ich habe den Code aktualisiert, um die Zeichenfolge vor der Änderung zu kopieren, was natürlich die Dinge verlangsamt. Ich habe auch Brian D Foys Vorschlag in einer anderen Antwort berücksichtigt, eine längere Zeichenfolge zu verwenden (obwohl eine Million wie übertrieben schien). Dies deutet jedoch auch darauf hin, dass Sie, bevor Sie den Trickstil auswählen, herausfinden, wie Ihre Stringlängen aussehen - die Vorteile des Tricks werden durch kürzere Saiten verringert. Bei allen Längen habe ich jedoch doppelte Gewinne getestet. Und für die Augen ist es immer noch einfacher.

Tanktalus zeigt einen Maßstab für sehr kleine Saiten, aber die Probleme werden schlechter, wenn die Saiten größer werden. In seinem Code habe ich den oberen Teil geändert:

my $a = 'a' x 1_000_000;

my @x = (
  "   $a   ",
  "$a    ",
  $a,
  "    $a"
  );

Ich bekomme diese Ergebnisse:

          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%      --

Wenn die Saite größer wird, sind die Verwendung von "Trick" und "Double" fast gleich und die gemeinsame Lösung, für die die meisten Menschen gehen, die "Single" (einschließlich mir, weil ich diese Gewohnheit nicht brechen kann, obwohl ich das weiß ), beginnt wirklich zu saugen.

Wenn Sie sich einen Benchmark ansehen, denken Sie darüber nach, was es Ihnen sagt. Um zu sehen, ob Sie es verstehen, ändern Sie die Daten und versuchen Sie es erneut. Machen Sie Arrays lang, Skalare groß und so weiter. Machen Sie Schleifen, Greps oder Regexes zu Beginn, in der Mitte und am Ende. Sehen Sie, ob die neuen Ergebnisse Ihrer Vorhersage entsprechen. Finden Sie heraus, was der Trend ist. Wird die Leistung immer besser, nähert sich einer Grenze, dem Höhepunkt und dem Ablehnen oder etwas anderem?

Komisch, du solltest das ansprechen!

Ich habe kürzlich gelesen Ein Artikel, in dem die Leistung von zwölf (!) verschiedenen TRIM -Implementierungen analysiert werden.

Obwohl der Artikel speziell die JavaScript Regex -Implementierung verwendet, verwendet er die Perl -Syntax, daher denke ich, dass er diese Diskussion entspricht.

Aus dem ketzerischen Streiten, warum machen Sie es überhaupt? Alle oben genannten Lösungen sind insofern "korrekt", als sie die Whitespace von beiden Seiten der Saite in einem Pass transportieren, aber keine ist furchtbar lesbar (erwarten Sie vielleicht vielleicht Dieses hier). Wenn das Publikum für Ihren Code nicht aus Perl-Codierern auf Expertenebene besteht, sollte jeder der oben genannten Kandidaten einen Kommentar haben, der beschreibt, was sie tun (wahrscheinlich eine gute Idee sowieso). Im Gegensatz dazu leisten diese beiden Zeilen dasselbe, ohne Lookaheads, Wildcards, Midichlorine oder irgendetwas zu verwenden, das für einen Programmierer mit moderatem Erfahrungen nicht offensichtlich ist:

$string =~ s/^\s+//;
$string =~ s/\s+$//;

Es gibt (wohl) einen Performance -Hit, aber solange Sie sich nicht mit einigen Mikrosekunden bei der Ausführung befassen, wird sich die zusätzliche Lesbarkeit lohnen. MEINER BESCHEIDENEN MEINUNG NACH.

Bitte schön: $x =~ s/\A\s*(.*?)\s*\z/$1/;

$ x = ~ s/(^ s+) | ( s+$) // g;

Normalerweise mache ich es so:

($foo) = $foo =~ /^\s*(.*?)\s*$/;

Alles zwischen den führenden Räumen und den nachverfolgenden Räumen wird gruppiert und zurückgegeben, sodass ich es derselben alten Variablen zuweisen kann.

Oder dieses: s/\A\s*|\s*\Z//g

s/^\s*(\S*\S)\s*$/$1/
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
$x =~ s/^\s*(.*?)\s*$/$1/;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top