[英]Matching Dollar Sign in Perl String
Perl 程序中包含美元 ($) 符號的簡單文本字符串:
open my $fh, "<", $fp or die "can't read open '$fp': $OS_ERROR";
while (<$fh>)
{
$line=''; #Initialize the line variable
$line=$_; #Reading a record from a text file
print "Line is $line\n"; #Printing for confirming
(@arr)=split('\|',$line);
$line 獲取以下管道分隔的字符串(通過打印 $line 值確認):
Vanilla Cake $3.65 New Offering|Half pound Vanilla Cake||Cake with vanilla, cream and cheese
然后將該記錄拆分並拉入特定的數組元素:
(@arr)=split('\|',$line);
$arr[0] 得到Vanilla Cake $3.65
, $arr 1得到Half pound Vanilla Cake
, $arr[2] 保持為empty/NULL
, $arr[3] 得到Cake with vanilla, cream and cheese
的蛋糕
現在我檢查 $arr[0] 是否包含價格值。 要匹配的模式是一些文本( Vanilla Cake
),然后是美元符號($),后跟一個或多個數字(在這種情況下為3
),十進制是可選的 - 可能存在或可能不存在,然后存在可以是小數點后的一位或多位數字(在這種情況下為.65
)。 使用以下正則表達式:
if ($arr[0]=~ /(.*?)(\$\d+(?:\.\d+)?)/)
{
print "match1 is $1, match2 is $2, match3 is $3, match4 is $4\n";
}
問題是 $1, $2, $3, $4 - 所有匹配的模式值都打印為 NULL/EMPTY。 我想這是因為 $ 符號是字符串 $arr[0] 的一部分。
我的猜測是,由於 $3.65 的價值,它將 $3 部分(小數點前)作為變量並嘗試替換它並且 $3 為 NULL。 所以正則表達式匹配正在發生購買價值提取可能會失敗,因為整個字符串可能被解釋為Vanilla Cake .65
,而不是Vanilla Cake $3.65
(這是我的猜測)
可能這就是正則表達式匹配和提取失敗的原因。
我還在某處讀到它可能依賴於變量初始化( $line
或$arr[0]
作為單引號或雙引號) - 我不知道這種依賴關系(這就是為什么包括所有代碼,如 $line 的初始化變量如上)。 $line 一次從文件中讀取一條記錄,因此需要在每次迭代時進行初始化。
已嘗試在Escape a dollar sign inside a variable和Trouble escaping $ sign in Perl中給出的解決方案,但無法使其正常工作。 在https://regex101.com/r/FQjcHp/2/上創建正則表達式的其他試驗和錯誤也無濟於事。
有人可以讓我知道如何使用正確的正則表達式代碼從上述字符串中獲取Vanilla Cake
和$3.65
的值嗎?
PS:添加使用相同代碼運行的在線編譯器的屏幕截圖,可以正常工作並正確捕獲 $ 值。 不知何故,在我的程序中它並沒有撿起它。
這段代碼
if ($foo =~ /(.*?)(\$\d+(?:\.\d+)?)/) {
print "match1 is $1, match2 is $2, match3 is $3, match4 is $4\n";
}
有了這個輸入
Vanilla Cake $3.65
將打印
Use of uninitialized value $3 in concatenation (.) or string at ...
Use of uninitialized value $4 in concatenation (.) or string at ...
match1 is Vanilla Cake , match2 is $3.65, match3 is , match4 is
如果您沒有啟用use warnings
,警告將保持沉默。
這就是您提供的代碼對此輸入的作用。 您還表明它與您的屏幕截圖有關。 您在評論中說,它不會在您的家用 PC 上執行此操作。 我會說這是不可能的。
您的代碼不同,您的輸入不同,或者您的 Perl 安裝不同(盡管這不太可能是問題)。 真的別無選擇。
一個大問題是您沒有使用use strict; use warnings
在您的代碼中use strict; use warnings
。 這可能意味着您的代碼的任何數量的問題都被隱藏了。 在您的情況下,我很可能會說這是一個錯字,例如:
$Iine = $_;
if ($line =~ /...../) # <---- not the same variable
但是您要求 8 小時更新您的代碼,所以我想我們會在 8 小時內找到答案。
幾點建議
while (<$fh>)
{
$line=''; #Initialize the line variable
$line=$_; #Reading a record from a text file
<$fh>
正在執行此操作。while (my $line = <$fh>)
。$3
和$4
永遠不能保存值,因為您缺少必要的捕獲組( ... )
。 兩個捕獲組意味着只有$1
和$2
將被填充。use strict;
use warnings;
因為不這樣做不會幫助你,它只會隱藏你的問題。
還要養成將聲明( my $var
)放在盡可能小的范圍內的習慣。 示例代碼:
use strict;
use warnings;
use feature 'say';
while (my $line = <DATA>) {
my @x = split /\|/, $line;
if ($x[0] =~ /(.*?)(\$\d+(?:\.\d+)?)/) {
say "$1 is $2";
}
}
__DATA__
Vanilla Cake $3.65 New Offering|Half pound Vanilla Cake||Cake with vanilla, cream and cheese
大約 2 年前,我遇到了一個類似的問題 - 並且不得不打破我的頭超過 5 天,然后我才能用巨大的 $ 符號找到問題的根源。 事情是這樣的:
美元正則表達式值未打印 - 類似於您所觀察到的。
很久以前有人編寫的 perl 代碼用雙引號初始化了字符串 var。 就像是
$string="This is some text";
在我觸摸它之前它工作得很好。 :-)
我所做的是在其中插入了一個變量,例如
$string="This is some $PriceVariableHavingDollarSign text";
然后我嘗試在 $string 變量上運行與美元匹配的正則表達式,希望能檢測到美元。 不完全是,但與您嘗試執行的操作非常相似,如下所示:
$string=~ /(.*?)(\$\d+(?:\.\d+)?)/
它要么給出編譯錯誤,要么無法使用我嘗試的不同正則表達式組合完全拾取美元符號。
所以我的回答兼建議是檢查你的“冗長代碼”,如果你的變量上的雙引號發生了類似的事情。 最有可能的是,這可能會導致問題。
在從源頭獲取值之前,如果可能,請嘗試在 $ 符號上使用 \,例如(至少這解決了我的問題)。 代替
PriceVariableHavingDollarSign = "Cake is $3.5";
嘗試擁有
$PriceVariableHavingDollarSign ="Cake is \$3.5";
這是對 Perl 中雙引號和單引號發生的情況的一個很好的解釋。 https://www.effectiveperlprogramming.com/2012/01/understand-the-order-of-operations-in-double-quoted-contexts/
對於您在問題、評論和圖片中提出的明確細節,做得很好。 它可以幫助您獲得所有可能的角度、場景和解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.