Esiste un'espressione regolare compatibile con Perl per tagliare gli spazi bianchi da entrambi i lati di una stringa?

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

  •  06-07-2019
  •  | 
  •  

Domanda

C'è un modo per farlo in una riga?

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

In altre parole, rimuovi tutti gli spazi bianchi iniziali e finali da una stringa.

È stato utile?

Soluzione

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

o

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

Altri suggerimenti

La mia prima domanda è ... perché? Non vedo nessuna delle soluzioni a regexp singola più leggibile rispetto alla regexp con cui hai iniziato. E sicuramente non sono neanche lontanamente vicini.

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

fornisce risultati sulla mia macchina di:

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

Modifica : runrig ha ragione, ma con pochi cambiamenti. Ho aggiornato il codice per copiare la stringa prima della modifica, che ovviamente rallenta le cose. Ho anche preso in considerazione il suggerimento di Brian D Foy in un'altra risposta per usare una stringa più lunga (sebbene un milione sembrasse eccessivo). Tuttavia, ciò suggerisce anche che prima di scegliere lo stile del trucco, capisci come sono le lunghezze delle corde: i vantaggi del trucco sono ridotti con stringhe più brevi. In ogni caso, ho provato a vincere due volte. Ed è ancora più facile per gli occhi.

Tanktalus mostra un punto di riferimento per stringhe molto piccole, ma i problemi peggiorano man mano che le stringhe diventano più grandi. Nel suo codice, ho modificato la parte superiore:

my $a = 'a' x 1_000_000;

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

Ottengo questi risultati:

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

Man mano che la stringa diventa più grande, usando " trick " e "doppio" sono quasi uguali e la soluzione comune per la maggior parte delle persone, il "singolo" (incluso me, perché non riesco a rompere quell'abitudine anche se lo so), inizia davvero a fare schifo.

Ogni volta che guardi un benchmark, pensa a cosa ti sta dicendo. Per capire se lo capisci, modifica i dati e riprova. Crea array lunghi, scalari grandi e così via. Fai in modo che loop, greps o regex trovino materiale all'inizio, al centro e alla fine. Verifica se i nuovi risultati corrispondono alla tua previsione. Scopri qual è la tendenza. Le prestazioni migliorano sempre di più, si avvicinano a un limite, il picco inizia a declinare o qualcos'altro?

Divertente dovresti parlarne!

Di recente ho letto un articolo che analizza le prestazioni di dodici (!) diverse implementazioni di trim .

Sebbene l'articolo utilizzi specificamente l'implementazione di regex JavaScript, utilizza la sintassi Perl, quindi penso che sia appropriato per questa discussione.

Discutendo dall'eretico, perché farlo affatto? Tutte le soluzioni di cui sopra sono "corrette" in quanto tagliano gli spazi bianchi da entrambi i lati della stringa in un passaggio, ma nessuno è terribilmente leggibile (aspettarsi forse questa espressione ). A meno che il pubblico per il tuo codice non sia composto da programmatori Perl di livello esperto, ciascuno dei candidati di cui sopra dovrebbe avere un commento che descriva ciò che fanno (probabilmente comunque una buona idea). Al contrario, queste due linee realizzano la stessa cosa senza usare lookaheads, caratteri jolly, midichlorines o qualsiasi cosa che non sia immediatamente ovvia per un programmatore di esperienza moderata:

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

C'è (probabilmente) un colpo di prestazione, ma fintanto che non ti preoccuperai di alcuni microsecondi durante l'esecuzione, ne varrà la pena la leggibilità aggiunta. IMHO.

Ecco qua: $ x = ~ s / \ A \ s * (. *?) \ s * \ z / $ 1 /;

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

Di solito lo faccio in questo modo:

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

Tutto tra gli spazi iniziali e gli spazi finali è raggruppato e restituito, quindi posso assegnarlo alla stessa vecchia variabile.

O questo: s/\A\s*|\s*\Z//g

s/^\s*(\S*\S)\s*$/$1/
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
$x =~ s/^\s*(.*?)\s*$/$1/;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top