我正在尝试制作一个验证以下格式的正则表达式:
我认为有效的示例:
4,31,2-22,8
29,1-10,2-12,9
我认为无效的示例:
4,31,2-22,8,
29,1-10,-2-12-,9
29,1-50,12-2,32
到目前为止,我的正则表达式如下:
yourDictionnary = open('Dictionary.txt', 'r').read().splitlines() #this puts contents from the dictionnary into a list line by line
theCsvContent = ','.join(open('csvName.csv', 'r').read().splitlines()).split(',') #this puts contents from the csv into a list element by element
for index, word in enumerate(theCsvContent): #loops through theCsv with index as the word index and word as the word we're iterating on
if word not in yourDictionnary: #checks if the word is in dictionnary and if not :
del theCsvContent[index] #removes the word from the csv
open('result.csv', 'w').write(','.join(theCsvContent)) #this writes the edited csv into result.csv
此表达式此刻使我很好地理解了“-”和“,”,并且数字从1到31。排名问题是第二个值大于第一个值,我不知道如何解决它。 有什么建议吗?
答案 0 :(得分:1)
正如Jeff已经建议的那样,我不会使用正则表达式,因为它很难理解。
解决方案比看起来简单得多:
function isValid($string)
{
$numbers = explode(',', $string);
// Covers the case when you have an empty value at the beginning/end of string.
if (count($numbers) !== count(array_filter($numbers))) {
return false;
}
foreach ($numbers as $number) {
if (is_numeric($number) && $number >= 1 && $number <= 31) {
continue;
}
if (!preg_match('/^(\d+)-(\d+)$/', $number, $matches)) {
return false;
}
if ($matches[1] >= 1 && $matches[1] <= 31 &&
$matches[2] >= 1 && $matches[2] <= 31 &&
$matches[2] > $matches[1]
) {
continue;
}
return false;
}
return true;
}
$strings = [
'4,31,2-22,8',
'29,1-10,2-12,9',
'4,31,2-22,8,',
'29,1-10,-2-12-,9',
'29,1-50,12-2,32',
];
foreach ($strings as $string) {
var_dump(isValid($string));
}
结果将是:
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
答案 1 :(得分:1)
我认为最好将正则表达式和常规代码结合使用。此函数检查整个字符串是否匹配以逗号分隔的数字或范围的模式,然后提取单个数字或范围,并对它们应用其他错误检查(在1到31之间,结束> =开头):
function validate_range($range) {
if (!preg_match('/^((\d+(?:-\d+)?)(?:,(?!$)|$))+$/', $range)) return false;
preg_match_all('/(\d+(?:-\d+)?)/', $range, $matches);
foreach ($matches[1] as $match) {
if (strpos($match, '-') !== false) {
list($start, $end) = explode('-', $match);
if ($end < $start) return false;
if ($start < 1 || $start > 31 || $end < 1 || $end > 31) return false;
}
if ($match < 1 || $match > 31) return false;
}
return true;
}
您可以像这样测试它:
$ranges = array(
'4,31,2-22,8',
'29,1-10,2-12,9',
'4,31,2-22,8,',
'29,1-10,-2-12-,9',
'29,1-50,12-2,32');
foreach ($ranges as $range) {
if (validate_range($range))
echo "$range is OK!\n";
else
echo "$range is no good\n";
}
输出:
4,31,2-22,8 is OK!
29,1-10,2-12,9 is OK!
4,31,2-22,8, is no good
29,1-10,-2-12-,9 is no good
29,1-50,12-2,32 is no good