正则expression式负向预测
在我的主目录中,我有一个包含Drupal平台的文件夹drupal-6.14。
从这个目录中我使用下面的命令:
find drupal-6.14 -type f -iname '*' | grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*' | xargs tar -czf drupal-6.14.tar.gz
这个命令的作用是gzips文件夹Drupal-6.14 ,不包括drupal-6.14 / sites / sites / all和sites / default所包含的所有子文件夹。
我的问题是正则expression式:
grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*'
该expression式的作品排除所有我想排除的文件夹,但我不明白为什么。
这是使用正则expression式的常见任务
匹配所有string,除了不包含子模式x的string。 换句话说,否定子模式。
我认为,我明白,解决这些问题的总体策略是使用负向预测,但是我从来没有理解到一个令人满意的程度如何正面和负面看(前/后)的工作。
多年来,我已经阅读了许多网站。 PHP和Python的正则expression式手册,其他页面如http://www.regular-expressions.info/lookaround.html等等,但我从来没有真正理解它们。
有人可以解释,这是如何工作,也许提供一些类似的例子,会做类似的事情?
– 更新一:
关于Andomar的回应:双重否定的前瞻可以更简洁地expression为一个积极的前瞻性陈述:
即是:
'drupal-6.14/(?!sites(?!/all|/default)).*'
相当于:
'drupal-6.14/(?=sites(?:/all|/default)).*'
???
– 更新二:
根据@andomar和@alan摩尔 – 你不能交换双向负向lookahead积极lookahead。
负向前视说,在这个位置,下面的正则expression式不能匹配。
我们来看一个简单的例子:
a(?!b(?!c)) a Match: (?!b) succeeds ac Match: (?!b) succeeds ab No match: (?!b(?!c)) fails abe No match: (?!b(?!c)) fails abc Match: (?!b(?!c)) succeeds
最后一个例子是双重否定 :它允许一个b
后跟c
。 嵌套的负向预测变成积极的预测: c
应该存在。
在每个例子中,只有a
被匹配。 向前看只是一个条件,并没有添加到匹配的文本。
Lookarounds可以嵌套。
所以这个正则expression式匹配“drupal-6.14 /”, 不是跟随“/ all”或“/ default”的“sites”。
混乱? 使用不同的词,我们可以说它匹配“drupal-6.14 /”, 除非 “/ all”或“/ default”后面跟着“sites”
如果你像这样修改你的正则expression式:
drupal-6.14/(?=sites(?!/all|/default)).* ^^
…它将匹配包含drupal-6.14/
之后的所有input,其次是sites
之后是除 /all
或/default
之外的任何其他input 。 例如:
drupal-6.14/sites/foo drupal-6.14/sites/bar drupal-6.14/sitesfoo42 drupal-6.14/sitesall
改变?=
?!
匹配你原来的正则expression式只是否定这些匹配:
drupal-6.14/(?!sites(?!/all|/default)).* ^^
所以,这仅仅意味着drupal-6.14/
现在不能被sites
跟随/all
或/default
以外的任何其他 sites
。 所以现在, 这些input将满足正则expression式:
drupal-6.14/sites/all drupal-6.14/sites/default drupal-6.14/sites/all42
但是,其他一些答案(也可能是你的问题)中可能并不明显的是,你的正则expression式也允许其他的input,而drupal-6.14/
之后的其他input也是非sites
。 例如:
drupal-6.14/foo drupal-6.14/xsites
结论:所以,你的正则expression式基本上说包括drupal-6.14
所有子目录, 除了名称以非all
或default
之外的其他名称开头的那些子目录。