我有一個 Perl 腳本,我在其中回圈執行 Web 服務呼叫。服務器回傳一個多值 HTTP 標頭,我需要在每次呼叫后決議該標頭,其中包含進行下一次呼叫所需的資訊(如果它不回傳標頭,我想退出回圈)。
我只關心標題中的一個值,我需要使用正則運算式從中獲取資訊。假設標題是這樣的,我只關心“foo”值:
X-Header: test-abc12345; blah=foo
X-Header: test-fgasjhgakg; blah=bar
我能得到這樣的標頭值:@values = $response->header( 'X-Header' );。但是我如何快速檢查是否
- 有一個 foo 值,并且
- 決議并保存下一次迭代的 foo 值?
理想情況下,我想做這樣的事情:
my $value = 'default';
do {
# (do HTTP request; use $value)
@values = $response->header( 'X-Header' );
} while( $value = first { /(?:test-)([^;] )(?:; blah=foo)/ } @values );
但是grep, first(from List::Util) 等都會回傳整個匹配項,而不僅僅是我想要的單個捕獲組。我想通過回圈遍歷陣列并在回圈體內匹配/決議來避免弄亂我的代碼。
我想要的可能嗎?什么是最緊湊的撰寫方式?到目前為止,我能想到的就是使用環視并\K丟棄我不關心的東西,但這不是超級可讀的,并且使正則運算式引擎執行了許多不必要的步驟。
uj5u.com熱心網友回復:
所以看起來你想用某種模式捕捉第一個元素,但只獲取模式。你希望它做得很好。確實,first并且grep只傳遞元素本身。
但是,List::MoreUtils::first_result確實支持處理其匹配
use List::MoreUtils 0.406 qw(first_result);
my @w = qw(a bit c dIT); # get first "it" case-insensitive
my $res = first_result { ( /(it)/i )[0] } @w;
say $res // 'undef'; #--> it
這( ... )[0]需要把正則運算式串列中的情況下,使其回傳實際拍攝。另一種方式是firstres { my ($r) = /(it)/i; $r }。選擇您的選擇
對于問題中的資料
use warnings;
use strict;
use feature 'say';
use List::MoreUtils 0.406 qw(firstres);
my @data = (
'X-Header: test-abc12345; blah=foo',
'X-Header: test-fgasjhgakg; blah=bar'
);
if (my $r = firstres { ( /test-([^;] );\s blah=foo/ )[0] } @data) {
say $r
}
列印abc12345,在評論中澄清為尋求的結果。
0.406(2015-03-03)之前的模塊版本沒有firstres(別名first_result)
uj5u.com熱心網友回復:
first { ... } @values回傳一個值(或undef)。
您可以使用以下任一方法:
my ($value) = map { /...(...).../ } @values;
my $value = ( map { /...(...).../ } @values ) ? $1 : undef;
my $value = ( map { /...(...).../ } @values )[0];
使用first,它看起來像下面這樣,這很愚蠢:
my $value = first { 1 } map { /...(...).../ } @values;
但是,假設捕獲不能是空字串或字串0,則first_result可以使用List::MoreUtils來避免不必要的匹配:
my $value = first_result { /...(...).../ ? $1 : undef } @values;
my $value = first_result { ( /...(...).../ )[0] } @values;
如果回傳的值可能是假的(例如一個空字串或 a 0),你可以使用類似的東西
my $value = first_result { /...(...).../ ? \$1 : undef } @values;
$value = $$value if $value;
該first_result方法在實踐中不一定更快。
uj5u.com熱心網友回復:
下面的代碼片段是尋找foo存盤在一個變數中$find,找到的值存盤在變數中$found。
my $find = 'foo';
my $found;
while( $response->header( 'X-Header' ) ) {
if( /X-Header: .*?blah=($find)/ ) {
$found = $1;
last;
}
}
say $found if $found;
示例演示代碼
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $find = 'foo';
my $found;
my @header = <DATA>;
chomp(@header);
for ( @header ) {
$found = $1 if /X-Header: .*?blah=($find)/;
last if $found;
}
say Dumper(\@header);
say "Found: $found" if $found;
__DATA__
X-Header: test-abc12345; blah=foo
X-Header: test-fgasjhgakg; blah=bar
輸出
$VAR1 = [
'X-Header: test-abc12345; blah=foo',
'X-Header: test-fgasjhgakg; blah=bar'
];
Found: foo
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/316263.html
下一篇:如何遍歷多個Perl陣列
