我正在尝试匹配文件名中不需要的区域以删除文件。
如果REGEX找到一个“坏区域” (Brazil or Columbia)
,但我想得到任何匹配项,但是如果它们与同一括号(USA, UK, Europe, Australia)
中的“好区域”混在一起,我想得到任何匹配项。
我有一个正则表达式
(?<![( ](USA)[,)])[( ](Brazil|Columbia)[,)](?![( ](USA|UK|Europe|Australia)[,)])
FIFA Soccer (USA, Brazil) <<< DON't MATCH IF USA IS IN SAME BRACKET BEFORE
FIFA Soccer (Brazil, USA) <<< DON't MATCH IF USA IS IN SAME BRACKET AFTER
FIFA Soccer (Brazil) <<< MATCH
FIFA Soccer (Brazil, Ireland) <<< MATCH
FIFA Soccer (Moon, Brazil) <<< MATCH
到目前为止,正确的行是匹配的,但这是因为我有一个固定宽度的“ negative lookbehind”在寻找“ USA”……但是我也希望在我的国家中包含“ UK”,“ Europe”和“ Australia”负面的回望,我不能这样做,因为它们必须是“固定宽度” ...
FIFA Soccer (UK, Brazil) <<< ERROR - THIS ONE SHOULDN'T MATCH AND DOES
FIFA Soccer (Brazil, UK) <<< This one works (no match) because I have my lookahead set up
观看现场演示: Here
因此,有一种方法可以使REGEX开头的(?<![( ](USA|UK|Europe|Australia)[,)])
之类的东西生效,以使UK, Brazil
和Europe, Brazil
之类的东西不匹配。
答案 0 :(得分:0)
您可以使用
\((?!(?:[^()]*,\s*)?(?:USA|UK|Europe|Australia)\s*[,)])[^()]*\)
请参见regex demo
详细信息
\(
-一个(
字符(?!(?:[^()]*,\s*)?(?:USA|UK|Europe|Australia)\s*[,)])
-负前瞻,如果在右侧立即有匹配项,则匹配失败
(?:[^()]*,\s*)?
-的可选序列
[^()]*
-除(
和)
以外的0多个字符,
-逗号\s*
-超过0个空格(?:USA|UK|Europe|Australia)
-好的价值之一\s*
-超过0个空格[,)]
-一个,
或)
[^()]*
-除(
和)
以外的0个或更多字符\)
-一个)
字符。答案 1 :(得分:0)
您可以交替使用PCRE动词(*SKIP)(*F)
来匹配和拒绝匹配,而不是使用可变长度的负向查找:
(?:USA|UK|Europe|Australia),\h*(?:Brazil|Austria)[,)](*SKIP)(*F)|(?:Brazil|Austria)[,)](?!\h?(?:USA|UK|Europe|Australia)[,)])
(*FAIL)
的行为类似于失败的否定断言,并且是(?!)
的同义词(*SKIP)
定义了一个点,当子模式稍后失败时,不允许正则表达式引擎回溯(*SKIP)(*FAIL)
一起提供了一个很好的限制选择,即您不能在上述正则表达式中留有可变长度。您可以在PCRE中使用DEFINE
动词来避免正则表达式中的重复,如下所示:
/
(?(DEFINE) # use define to avoid repetitions
(?<ct>USA|UK|Europe|Australia) # disallow countries
(?<mct>Brazil|Austria) # matching countries
)
# main regex starts here
(?&ct),\h*(?&mct)[,)](*SKIP)(*F)
|
(?&mct)[,)](?!\h?(?&ct)[,)])
/x
答案 2 :(得分:0)
使用模式提取国家/地区名称和array_filter
:
$filenames = ['FIFA Soccer (USA, Brazil)',
'FIFA Soccer (Brazil, USA)',
'FIFA Soccer (Brazil)',
'FIFA Soccer (Brazil, Ireland)',
'FIFA Soccer (Moon, Brazil)'];
$bad = ['Brazil', 'Columbia'];
$good = ['USA', 'UK', 'Europe', 'Australia'];
$todelete = array_filter($filenames, function ($i) use ($bad, $good) {
$countries = preg_match_all('~(?:\G(?!\A), |\()\K\pL+~', $i, $m) ? $m[0] : [];
return array_intersect($countries, $bad) && !array_intersect($countries, $good);
});
print_r($todelete);