簡體   English   中英

s /^(.*?)的正則表達式:\\ s * //

[英]the regular expression of s/^(.*?):\s*//

在下面的Perl示例中,使用正則表達式,即next unless s/^(.*?):\\s*//; 但是,如何理解此正則表達式s/^(.*?):\\s*//

while ( <> ) {
next unless s/^(.*?):\s*//;
$HoA{$1} = [ split ];
}

它捕獲(並存儲為$1 )一些文本到一個: 然后,它將刪除捕獲的文本,分號和任何尾隨空格。

除正則表達式之外:如果正則表達式成功完成了其工作,則代碼會將捕獲的文本用作哈希鍵,其值是數組引用。 該數組的元素是在空格上分割的其余行。

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

my %HoA;

while ( <DATA> ) {
  #next unless s/^(.*?):\s*//;
  next unless 
    s/      #s is replace match operation
      ^     #start at the beginning of the line
      (     #begin capture $1
        .*? #capture anything, but not greedy, i.e. stop before :
      )     #end capture $1
      :     #literal colon (must match)
      \s*   #optional whitespace
    //x;    #replace match with nothing, x flag allows formatting and comments
  $HoA{$1} = [ split ];
}

print Dumper(\%HoA), "\n";

__DATA__

Thingy: Thing1 Thing2
Stuff: mystuff yourstuff
other line that doesn't have a colon

$VAR1 = {
          'Thingy' => [
                        'Thing1',
                        'Thing2'
                      ],
          'Stuff' => [
                       'mystuff',
                       'yourstuff'
                     ]
        };

它從第( ^ )行開始到:匹配,捕獲( (.*?) )和隨后的任何空格( \\s* )之間的內容,並將其( s/regex/replacement/s/regex/replacement/為空串。

如果匹配,則返回true值(進行替換的次數),否則返回false。

例如,當$_foo: bar ,它將與foo:匹配並被替換,從而導致$_bar 之后,第一個捕獲組$1將包含foo

要了解更多信息,請查看:

他們使用了許多人不再使用的舊式快捷方式。 這又是缺少默認變量的代碼。 我也將“ unless語句反轉為更標准的格式。 也就是說,我將其設為if語句,並將next一個語句作為if塊的一部分:

while ( $_ = <> ) {
    if (not $_ =~ s/^(.*?):\s*//) {
       next;
    }
    $HoA{$1} = [ split(/\s+/, $_) ];
}

因此,我們從菱形運算符設置$_的值。 這基本上是在命令行上獲取文件的名稱,並讀取這些文件中的每一行。 如果命令行上沒有文件,它將從STDIN讀取。

正則表達式比較棘手。 ^將正則表達式錨定到行的開頭。 否則,正則表達式可以出現在該行的任何位置。 例如:

/FOO/    #Will match "FOOBAR"  "BARFOOBAR", or "BARFOO"
/^FOO/   #Will only match "FOOBAR" and not "BARFOOBAR" or "BARFOO"

. 表示任何字符。 *表示零個或多個。 因此, .*表示任意數量的字符(包括零個字符。例如:

/^.*:/   #Will match any combination of characters followed by a colon (:).

因此,這將匹配:僅靠一行(零個或多個),或者this is a test:

棘手的部分是? 這會以非常微妙的方式改變*的含義。 通常,正則表達式是貪婪的。 他們嘗試匹配最大匹配,因此,如果您有一個字符串:

my $string = "abc:def:ghij";
$string =~ /^.*:/;

正則表達式將匹配最大的匹配項。 因此,上面的代碼將匹配abc:def:因為它是最長的以冒號結尾的字符串。 通過把? * ,將正則表達式設置為非貪婪的 -即它將匹配最小的表達式。 從而:

my $string = "abc:def:ghij";
$string =~ /^(.*):/   #Matches "abc:def:
$string =~ /^(.*?):/  #Matches "abc:"

\\s表示任何空格,通常表示空格或制表符。 *表示零個或多個這些空格。 因此,這可能不是空格或多個空格。

my $string = "abc:def:  foo";
$string =~ /^(.*?):\s*/;   #Matches "abc:"
$string = "abc:   This is a test";
$string =~ /^(.*?):\s*/;   #Matches "abc:   "

現在,正則表達式前面的s表示替換。 基本格式為:

$string =~ s/regex/string/;

其中regex是一個與$string中的內容匹配的正則表達式,而string是該匹配項的替換。 一個簡單的例子是:

$string = "My name is David";
$string =~ s/David/Bill/;    #String is now "My name is Bill"

在這種情況下,正則表達式匹配的字符將被替換為空。 也就是說,它們已從字符串中刪除:

$string = "abc:  def";
$string =~ /^(.*?):\s*/;   #$string is now "def". "abc:   " has been removed

因此,再看一下您的代碼:

while ( $_ = <> ) {
    if (not $_ =~ s/^(.*?):\s*//) {
       next;
    }
    $HoA{$1} = [ split(/\s+/, $_) ];
}

這是從命令行或STDIN上列出的文件中讀取的,並且正在尋找包含冒號的行。 如果該行不包含冒號,它將讀取下一行。

如果一行包含冒號,則從字符串中去除字符串的第一部分,直到第一個冒號,然后再跟隨任何空白。

$1指的是字符串的與前一個正則表達式的括號內匹配的部分。 那是字符串的第一部分,直到第一個冒號。 split是將由空格分隔的字符串的其余部分拆分,並使其成為所謂的匿名列表 也就是說,這將創建數組的哈希(這就是為什么將此哈希稱為HoA (數組的哈希)的原因)。

讓我們給出一些字符串示例:

____________________________________________________
|     STRING      |           RESULTS              |
|_________________|________________________________|
| abc:  foobar    | $HoA{abc} = ["foobar"]         |
| def:bar fu      | $HoA{def} = ["bar", "fu"]      |
| ghi:jkl:mno     | $HoA{ghi} = ["jkl:mno"]        |
| ghi :  jkl: mn: | $HoA{"ghi "} = ["jkl:", "mn:"] |
|_________________|________________________________|

請注意,最后一個鍵的末尾將有一個空格。 它是“ ghi”而不是“ ghi”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM