Existe uma expressão regular compatível com Perl para aparar o espaço em branco de ambos os lados de uma corda?

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

  •  06-07-2019
  •  | 
  •  

Pergunta

Existe uma maneira de fazer isso em uma linha?

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

Em outras palavras, remova todo o espaço em branco principal e à direita de uma corda.

Foi útil?

Solução

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

ou

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

Outras dicas

Minha primeira pergunta é ... por quê? Não vejo nenhuma das soluções de um único regexp ser mais legível do que o regexp que você começou. E eles com certeza não são tão rápidos.

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

fornece resultados na minha máquina de:

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

Editar: Runrig está certo, mas para pouca mudança. Atualizei o código para copiar a string antes da modificação, o que, é claro, diminui as coisas. Também levei em consideração a sugestão de Brian D Foy em outra resposta para usar uma corda mais longa (embora um milhão parecesse um exagero). No entanto, isso também sugere que, antes de escolher o estilo de truque, você descobre como são os comprimentos das suas cordas - as vantagens do truque são diminuídas com cordas mais curtas. Em todos os comprimentos que testei, porém, vitórias duplas. E ainda é mais fácil para os olhos.

TankTalus mostra uma referência para cordas muito pequenas, mas os problemas pioram à medida que as cordas aumentam. Em seu código, mudei a parte superior:

my $a = 'a' x 1_000_000;

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

Eu recebo estes resultados:

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

À medida que a corda fica maior, usar "truque" e "duplo" é quase o mesmo, e a solução comum que a maioria das pessoas procura, o "single" (inclusive eu, porque não posso quebrar esse hábito, mesmo sabendo disso ), realmente começa a ser péssimo.

Sempre que você olha para uma referência, pense no que está lhe dizendo. Para ver se você entende, altere os dados e tente novamente. Faça matrizes longas, escalares grandes e assim por diante. Faça loops, greps ou regexes encontre coisas no início, no meio e no final. Veja se os novos resultados correspondem à sua previsão. Descubra qual é a tendência. O desempenho fica cada vez melhor, aborda um limite, o pico e começa a declinar ou outra coisa?

Engraçado você deve trazer isso à tona!

Eu li recentemente Um artigo analisando o desempenho de doze (!) implementações de acabamento diferentes.

Embora o artigo use especificamente a implementação do JavaScript Regex, ele usa a sintaxe Perl, então acho que é apropriado para esta discussão.

Argumentando do herético, por que fazer isso? Todas as soluções acima estão "corretas", pois aparecem o espaço em branco de ambos os lados da corda em um passe, mas nenhum é terrivelmente legível (espere talvez Este). A menos que o público para o seu código seja composto por codificadores Perl de nível especialista, cada um dos candidatos acima deve ter um comentário descrevendo o que eles fazem (provavelmente uma boa ideia de qualquer maneira). Por outro lado, essas duas linhas realizam a mesma coisa sem usar lookaheads, curingas, midicloros ou qualquer coisa que não seja imediatamente óbvia para um programador de experiência moderada:

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

Existe (sem dúvida) um sucesso de desempenho, mas desde que você não esteja preocupado com alguns microssegundos na execução, a legibilidade adicional valerá a pena. NA MINHA HUMILDE OPINIÃO.

Aqui está: $x =~ s/\A\s*(.*?)\s*\z/$1/;

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

Eu costumo fazer assim:

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

Tudo entre os espaços principais e os espaços à direita é agrupado e retornado, para que eu possa atribuí -lo à mesma variável antiga.

Ou isto: s/\A\s*|\s*\Z//g

s/^\s*(\S*\S)\s*$/$1/
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
$x =~ s/^\s*(.*?)\s*$/$1/;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top