我可能在上一個問題中混淆了真正的問題,所以這里是:
假設您想知道 to 中的字符7是否15都1在字串中:
my $str = "011000001111111111000011111110110111110000101010111";
my $i = 7, $j = 15; # => start and end positions of the substring
my $l = $j - $i 1; # => length of the substrings
我想了一些合理的方法來做檢查
# 1. with `substr` and a regex:
printf "#1: %d\n", substr($str,$i,$l) =~ /\A1*\Z/;
# 2. with a regex from the beginning of the string:
printf "#2: %d\n", $str =~ /\A.{$i}1{$l}/;
# 3. with a regex and `pos`:
pos($str) = $i;
printf "#3: %d\n", $str =~ /1{$l}/;
我希望所有結果都是0(錯誤的),但我得到:
#1: 0
#2: 0
#3: 1
pos在#3中使用時正確的正則運算式是什么?
uj5u.com熱心網友回復:
你可以用一個簡單的正則運算式來做到這一點。
/\A\d{6}1{9}/
展開解釋...
m{
\A # the beginning of the string
\d{6} # any six digits (digits 1 to 6)
1{9} # 9 1's (digits 7 to 15)
# and we don't care about the rest
}x
通常的方法是使用位掩碼。
# Convert the string to binary.
my $str = "011000001111111111000011111110110111110000101010111";
my $num = oct("0b$str");
# This is your bitmask.
my $mask = 0b000000001111111111000000000000000000000000000000000;
# AND each bit together. If the result equals the mask, it matches.
print "Match" if ($num & $mask) == $mask;
優點是這可能更快更容易理解(如果您知道位掩碼是什么)。
缺點是這最多只能作業 64 位,假設你的 Perl 是為 64 位編譯的,它應該在 2022 年編譯,并且只能用于 1 和 0。
uj5u.com熱心網友回復:
可以用正則運算式遍歷字串
while (/(.)/g) { say "At pos ", pos, " is: $1" }
如果字串相當大,并且您寧愿從字串下方的位置開始,如評論中所述,那么首先發出pos = $start_pos;然后運行上面的正則運算式。
或者在所有位置獲取字符并檢查您關心的陣列
my @positions = 7 .. 15;
my @chars = split '';
for my $pos (@positions) { say "At $pos have: @chars[$pos-1]" }
但我寧愿準備和使用 Schwern 的回答中的位掩碼,如果它是1/ 0。
uj5u.com熱心網友回復:
兩個問題。
當您不使用
/g時,正則運算式引擎從位置零開始匹配。使用/g將注意您設定的位置。當正則運算式引擎無法在給定位置找到匹配項時,它將嘗試在稍后的開始位置找到匹配項。為防止這種情況,您需要使用
\G.
$ perl -Mv5.14 -e'
$_ = "xyx";
pos = 1;
say scalar( /\Gx/g ) ? "match at $-[0]" : "[no match]";
'
[no match]
$ perl -Mv5.14 -e'
$_ = "xyx";
pos = 2;
say scalar( /\Gx/g ) ? "match at $-[0]" : "[no match]";
'
match at 2
uj5u.com熱心網友回復:
最有效的代碼基于上一個答案中描述的位圖掩碼。
在此代碼示例中,演示了其他兩種進行描述比較的方法,但與位掩碼方法相比,它們效率不高。
use strict;
use warnings;
use feature 'say';
my($sum,$str,$start,$end,$length,@chars);
$sum = 0;
# 12345678901234567890
$str = '01100000111111111100001111111011';
($start,$end) = (7,15);
$length = 1 $end-$start;
say "** Method #1";
@chars = (split('', $str))[$start-1..$end-1];
$sum = $_ for @chars;
say $sum == $length
? 'All good'
: 'No dice';
say "** Method #2";
say $str =~ /^.{6}1{$length}/
? 'All good'
: 'No dice';
say "
But nothing can beat binary comparison given in
previous answer
";
輸出
** Method #1
No dice
** Method #2
No dice
But nothing can beat binary mask given in
previous answer
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/506238.html
標籤:perl
上一篇:將翻譯限制為短語中的一個單詞?
