我正在撰寫一個程式來存盤家庭成員的資料。
輸入格式如下,
Country Husband wife child pet
示例輸入
Japan ken Annie may money
輸入區域,丈夫,妻子,孩子和寵物的名字,并用空格分隔,我想檢查用戶輸入是否正確。我試過了
( /^(. )(\s(. )){4}$/ ) ? print "good" : print "fail";
但它只能判斷是否輸入了超過 5 個單詞,而不是準確判斷 5 個。比如,如果輸入
Japan ken Annie may money hank queen
仍然會通過判斷。
請告訴我我做錯了什么以及如何解決?
uj5u.com熱心網友回復:
使用一個好的庫來讀取輸入。? Getopt::Long非常好 ,有點標準
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
use List::Util qw(any);
my ($country, $husband, $wife, $child, $pet);
GetOptions(
'country=s' => \$country,
'husband=s' => \$husband,
'wife=s' => \$wife,
'child|kid=s' => \$child,
'pet=s' => \$pet
);
# If they all must be submitted, and no other input, check
usage() if any { not defined $_ } $country, $husband, $wife, $child, $pet;
usage() if @ARGV;
say "Family of $wife and $husband come from $country";
sub usage {
say STDERR "
Usage: $0 ...
All listed arguments are compulsory.
No other input is supported.
";
exit;
}
帶有多個單詞的選項值在引號下提供。我在上面展示了如何為輸入選項設定備用名稱,只要明確,它們可以縮短,可以洗掉一個連字符等。
program.pl --husband Ken -w "Jo Ann" -kid May
有關庫使用的更多功能,請參閱檔案。
在命令列上提交給程式的選項被放置在@ARGV 預定義的變數中。當庫決議輸入時,它會從@ARGV. 這允許我們傳遞其他輸入,通常是檔案名,然后我們可以使用 out @ARGV。(否則它們將被忽略。)
但是,如果您希望禁止任何其他輸入,請檢查@ARGV庫完成決議后是否沒有留下任何內容。
我使用List::Util來避免單獨檢查所有變數,但如果您想向用戶回傳錯誤輸入的特定訊息,請這樣做。
我將所有選項都設為小寫,因為問題中的大小寫不一致。請根據需要進行調整。
? 手動決議輸入給程式員帶來了很多負擔。
我們需要設計一個似乎適合我們目的的系統(可能很難提前判斷)——如何從命令列中拆分選項?多個單詞,特殊字符等呢?這是哪個外殼?順序——位置?(容易出錯并且很難檢查!)等。
然后我們需要對其進行決議,預測并捕獲各種可能的錯誤,可能會引入一些后處理。
大量的作業、除錯和測驗、迭代……結果很可能很脆弱,因此當將來要進行更改時,其余的(或全部?)可能需要重新作業。
這就是圖書館的用途;所有這一切,以及更多,都已經完成。
uj5u.com熱心網友回復:
在 stringJapan ken Annie may money hank queen上,您的第一個(. )是匹配Japan ken Annie的,因此正則運算式的其余部分能夠匹配四個額外的名稱而不會出現問題和匹配。
問題是那個點.匹配也是空格。
由空格(或任何其他分隔符)分隔的單詞的常見解決方案是使用以下運算式:
^ something (?: separator something )quantifier $ # Note: don't take into account spaces
(where 'something' cannot contain the separator)
所以在你的情況下,你可以寫:
^\S (?:\s \S ){4}$
其中\S 表示:任何非空白字符,1 次或多次
請注意,它\s匹配任何空白字符(包括新行)所以如果您正在閱讀整個檔案(而不是逐行),建議使用它\h(匹配水平空白字符)
^\S (?:\h \S ){4}$
如果您使用\s并且不逐行處理內容,則您的正則運算式可能會嘗試跨多行匹配資料,這對您的情況是錯誤的。
此外,如果您正在閱讀整個檔案,您可能還需要使用m修飾符
/^\S (?:\h \S ){4}$/m
或者
(?m)^\S (?:\h \S ){4}$
所以那^和$匹配行的開頭和結尾(而不是字串的結尾)
(?:)如果您不打算捕獲資料,請考慮使用非捕獲組。
如果您打算捕獲該行的所有資料,則可以改用此正則運算式:
^(\S )\h (\S )\h (\S )\h (\S )\h (\S )$
uj5u.com熱心網友回復:
輸入資料驗證很少可以通過簡單的正則運算式一步完成。
請檢查以下演示代碼以了解可能的國家/地區/名稱是否包含您的正則運算式建議的空格和破折號將無法正確處理。
為避免潛在的陷阱,請勿使用空格作為欄位分隔符——名稱和國家/地區可能包含空格/破折號——使用,填充更自然。
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $data;
my @header = split(/,/, <DATA>);
chomp @header;
while(my $line = <DATA>) {
chomp $line;
my @read = split(/,/,$line);
say "Warning: $line number of arguments is " . scalar @read
unless @read == 5;
$data->@{@header} = @read;
$data->{$_} =~ /[^a-z -] /i && say "Warning: '$_ => $data->{$_}' does not look right"
for @header;
say Dumper($data);
}
__DATA__
Country,Husband,wife,child,pet
Japan,ken,Annie,may,money
China,Sonny,Ae-Cha,Bora,coin,hummer
South Korea,Sonny2,Ae-Cha,Bora,coin
輸出樣本
$VAR1 = {
'Husband' => 'ken',
'pet' => 'money',
'child' => 'may',
'wife' => 'Annie',
'Country' => 'Japan'
};
Warning: China,Sonny,Ae-Cha,Bora,coin,hummer number of arguments is 6
$VAR1 = {
'Husband' => 'Sonny',
'pet' => 'coin',
'child' => 'Bora',
'wife' => 'Ae-Cha',
'Country' => 'China'
};
Warning: 'Husband => Sonny2' does not look right
$VAR1 = {
'Husband' => 'Sonny2',
'pet' => 'coin',
'child' => 'Bora',
'wife' => 'Ae-Cha',
'Country' => 'South Korea'
};
uj5u.com熱心網友回復:
請注意,如果您有一個可能包含空格的類別,則在空格上拆分字串不是一個好方法,例如“如果國家是韓國怎么辦?” 北極熊在他的回答中建議使用逗號作為分隔符,這將允許韓國。其他解決方法可能包括用空格參考單詞并使用可以處理參考的模塊,例如Text::ParseWordsPerl 中的核心模塊。
使用Text::ParseWords:
use strict;
use warnings;
use Data::Dumper;
use Text::ParseWords;
my $str = qq("South Korea" Ken Barbie Mario Fido);
my @data = quotewords(" ", 0, $str);
print Dumper \@data;
$VAR1 = [
'South Korea',
'Ken',
'Barbie',
'Mario',
'Fido'
];
但我認為計算單詞的主要問題最適合通過在空間上拆分字串并計算結果欄位來完成。您可以使用quotewords上述方法執行此操作,然后插入一個測驗,例如:
if (@data == 5) {
print "Correct number of args";
} elsif (@data < 5) {
print "Too few args";
} # etc.....
您也可以手動拆分字串:
my @data = split ' ', $str;
使用正則運算式進行計數的一種簡單方法是匹配您想要匹配的內容,然后將其分配給標量背景關系,使用一點 Perl 魔法:
my $count = () = $str =~ /\S /g; # how many non-whitespace matches do we get?
賦值中的空串列()會將正則運算式放入串列背景關系中,并將匹配數回傳給左側的標量。
但是我覺得使用單個字串資料輸入并不是最好的方法。如果您要獲取確切數量的輸入,為什么不單獨獲取它們呢?
use strict;
use warnings;
use Data::Dumper;
use feature 'say';
my
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/506215.html
上一篇:Perl:為do()列印編譯警告
