11

これを1行で行う方法はありますか?

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

つまり、文字列から先頭と末尾の空白をすべて削除します。

4

13 に答える 13

30

私の最初の質問は...なぜですか?あなたが始めた正規表現よりも読みやすい単一の正規表現ソリューションは見当たりません。そして、彼らは確かにそれほど速くはありません。

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

私のマシンで次の結果が得られます:

             レーティング シングル キャプチャー クラメルキャップ トリック ダブル
シングル 2541/s -- -12% -13% -96% -96%
キャプチャ 2902/s 14% -- -0% -95% -96%
kramercap 2911/s 15% 0% -- -95% -96%
トリック 60381/s 2276% 1981% 1974% -- -7%
double 65162/s 2464% 2145% 2138% 8% --

編集:runrigは正しいですが、ほとんど変わりません。変更前に文字列をコピーするようにコードを更新しましたが、これはもちろん速度を低下させます。また、別の回答で、より長い文字列を使用するという brian d foy の提案も考慮しました (100 万はやり過ぎのように見えましたが)。ただし、これは、トリック スタイルを選択する前に、ストリングの長さがどのようなものかを把握することも示唆しています。ストリングが短いほど、トリックの利点は少なくなります。しかし、私がテストしたすべての長さで、2 倍の勝利が得られました。そして、それはまだ目にやさしいです。

于 2008-10-08T20:48:56.463 に答える
26
$x =~ s/^\s+|\s+$//g;

また

s/^\s+//, s/\s+$// for $x;
于 2008-10-08T20:08:49.743 に答える
8

おかしい、これを持ち出すべきだ!

私は最近、12 (!) の異なるトリム実装のパフォーマンスを分析した記事を読みました。

この記事では特に JavaScript 正規表現の実装を使用していますが、Perl 構文を使用しているため、この議論に適していると思います。

于 2008-10-08T21:31:52.693 に答える
8

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

紐が大きくなるにつれて、「トリック」と「ダブル」の使い方はほとんど同じで、ほとんどの人が求める一般的な解決策は「シングル」です(私も含めて、これは知っていてもその習慣を破ることができないからです)。 )、本当に嫌になり始めます。

ベンチマークを見るときはいつでも、それが何を伝えているかを考えてください。理解しているかどうかを確認するには、データを変更してもう一度試してください。配列を長くしたり、スカラーを大きくしたりします。ループ、grep、または正規表現を作成して、最初、中間、および最後にあるものを見つけます。新しい結果が予測と一致するかどうかを確認します。どのような傾向があるかを把握します。パフォーマンスがどんどん良くなったり、限界に近づいたり、ピークに達してから低下し始めたりしますか?

于 2008-10-08T22:14:03.203 に答える
5

異端者からの議論、なぜそれをするのですか?上記の解決策はすべて、文字列の両側から空白を1回のパスで削除するという点で「正しい」ですが、ひどく読みやすいものはありません(おそらくこれを期待してください)。あなたのコードの対象者がエキスパート レベルの Perl コーダーで構成されていない限り、上記の各候補には、自分が何をするかを説明するコメントが必要です (いずれにせよ、おそらく良い考えです)。対照的に、これらの 2 つの行は、先読み、ワイルドカード、ミジクロリンなど、中程度の経験を持つプログラマーにはすぐにはわからないものを使用せずに、同じことを実現します。

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

(ほぼ間違いなく) パフォーマンス ヒットがありますが、実行時の数マイクロ秒を気にしない限り、追加された可読性はそれだけの価値があります。私見では。

于 2008-10-08T21:11:47.883 に答える
4

どうぞ:$x =~ s/\A\s*(.*?)\s*\z/$1/;

于 2008-10-08T20:06:06.877 に答える
2

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

于 2008-10-08T20:06:19.577 に答える
1

私は通常このようにします:

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

先頭のスペースと末尾のスペースの間のすべてがグループ化されて返されるので、同じ古い変数に割り当てることができます。

于 2008-10-08T23:02:20.750 に答える
0

またはこれ:s/\A\s*|\s*\Z//g

于 2008-10-08T20:07:23.020 に答える
0
s/^\s*(\S*\S)\s*$/$1/
于 2008-10-08T20:08:34.360 に答える
-1
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
于 2009-11-10T19:40:50.580 に答える
-2
$x =~ s/^\s*(.*?)\s*$/$1/;
于 2008-10-08T20:07:04.393 に答える