Existe uma expressão regular compatível com Perl para aparar o espaço em branco de ambos os lados de uma corda?
-
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.
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/;