我正在写一个程序来存储家庭成员的数据。
输入格式如下,
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
还是会通过审判的。
请告诉我我做错了什么,如何改正?
6条答案
按热度按时间gab6jxml1#
使用一个好的库来读取输入。† Getopt::Long是优秀的,实际上是一个标准
一个选项值有多个单词在引号中。我上面展示了如何为输入选项设置替代名称,它们可以被缩短,只要没有歧义,一个连字符可以被丢弃,等等。
有关库使用中更多功能,请参阅文档
在命令行上提交给Perl程序的选项被放置在
@ARGV
predefined variable中。(那些不以-
开头也不直接跟在-
后面的字符串)。这允许我们传递其他输入,通常是文件名,然后我们可以直接从@ARGV
中使用它们。(否则它们将被忽略。)因此,如果您希望抑制任何其他输入,请检查在库完成解析之后,
@ARGV
中是否没有任何内容。我使用List::Util来避免检查所有变量,但是如果你想向用户返回错误输入的特定消息,请这样做。
由于问题中的大小写不一致,我将所有选项都设为小写。请根据需要进行调整。
[2]手工解析输入给程序员带来了很大的负担。
我们需要设计一个看起来适合我们的目的的系统(可能很难提前告诉)--如何从命令行中分离选项?多个单词、特殊字符等情况如何?这是哪个shell的?顺序--位置?(容易出错,很难检查!)等等。
然后,我们需要解析它,预测并捕捉各种可能的错误,可能会引入一些后处理。
大量的工作,调试和测试,迭代...结果很可能是脆弱的,所以当未来有一个改变,其余的(或所有的?)可能需要返工。
这就是图书馆的作用所有这些,甚至更多,都已完成。
bwitn5fc2#
在字符串
Japan ken Annie may money hank queen
上,第一个(.+)
与Japan ken Annie
匹配,因此正则表达式的其余部分能够毫无问题地匹配四个额外的名称。问题是点
.
也匹配空格。对于由空格(或任何其他分隔符)分隔的单词,常用的解决方案是使用以下表达式:
所以在你的例子中,你可以写:
其中
\S+
表示:任何非空白字符,1次或多次请注意,
\s
匹配任何空白字符(包括新行)因此,如果您正在阅读整个文件(而不是逐行),建议使用\h
代替(匹配 horizontal 空白字符)如果您使用
\s
并且不逐行处理内容,则正则表达式可能会尝试跨多行匹配数据,这对于您的情况是错误的。此外,如果要阅读整个文件,则可能还需要使用
m
修饰符或
因此
^
和$
匹配行的开始和结束(而不是字符串的开始和结束)如果不打算捕获数据,请考虑使用非捕获组
(?:)
。如果您计划捕获该行的所有数据,则可以使用以下正则表达式:
ipakzgxi3#
使用简单的正则表达式很少能在一个步骤中完成输入数据验证。
请检查下面的演示代码,看是否有可能国家/名称中包含空格和破折号,这是您的正则表达式所建议的,将无法正确处理。
为了避免潜在的缺陷,不要使用空格作为字段分隔符--名称和国家/地区可能会包含空格/破折号--使用
,
填充更自然。输出样本
f45qwnt84#
请注意,如果您有一个可能包含空格的类别,以空格分割字串并不是一个好的方法,例如his answer中的“What if the country is South Korea?”Polar Bear建议使用逗号作为分隔符号,这将允许使用South Korea。其他的解决方法可能包括在引号中加上空格,以及使用可以行程引号的模块,例如
Text::ParseWords
。这是Perl中一个核心模块。使用
Text::ParseWords
:第一个
但是我认为最合适的方法是在空格上拆分字符串并计算得到的字段,你可以像上面那样用
quotewords
来计算,然后插入一个测试,例如:您也可以手动分割字串:
使用正则表达式进行计数的一种简单方法是匹配您想要匹配的内容,然后将其分配给一个标量上下文,使用一点Perl技巧:
赋值中的空列表
()
将把正则表达式放入列表上下文,并返回左侧标量的匹配数。但我觉得使用单个字符串数据输入并不是最好的方法,如果你有确切数量的输入要获取,为什么不单独获取呢?
输出量:
jtjikinw5#
问题出在
.
上,它与单词之间的空格相匹配。用答案的组成部分(例如字母、数字和破折号)来替换它会更好。也许有更好的解决办法,但这是我想到的。
hgc7kmma6#
在开始时第一个
.+
匹配整个字符串Japan ken Annie may money hank queen
,然后给予4个字符串,每个字符串匹配代码\s(.+)
,这是错误的。因此,代码的结果是:第1组
Japan ken Annie
第2组
您可以使用
\w+
而不是.+
来修复它。下面是一个演示:https://regex101.com/r/jQ8IE0/1