正则表达式负前瞻

在我的主目录中,我有一个包含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

该命令的作用是gzip压缩drupal-6.14文件夹,不包括drupal-6.14 / sites /的 所有子文件夹,但site / all和sites / default除外。


我的问题是关于正则表达式的:


grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*'

该表达式可以排除我要排除的所有文件夹,但是我不太明白为什么。


使用正则表达式


匹配所有字符串,但不包含子模式x的字符串除外。或者换句话说,否定子模式。


我(认为)我知道解决这些问题的一般策略是使用否定先行,但我从未完全满意地理解过分积极和消极的行事方式。


这些年来,我已经阅读了许多网站。PHP和Python regex手册以及其他页面,例如http://www.regular-expressions.info/lookaround.html等,但是我对它们从未真正有过深刻的了解。


有人可以解释这是如何工作的,也许可以提供一些类似的例子来做类似的事情?


-更新一:


关于Andomar的回应:双重否定前瞻能否更简洁地表达为单个肯定前瞻性陈述:


即是:


'drupal-6.14/(?!sites(?!/all|/default)).*'

相当于:


'drupal-6.14/(?=sites(?:/all|/default)).*'

???


-更新二:


根据@andomar和@alan moore-您不能将双负前瞻换为正前瞻。


尚方宝剑之说
浏览 499回答 3
3回答

回首忆惘然

否定的前瞻表示,在此位置,以下正则表达式无法匹配。让我们举一个简化的例子:a(?!b(?!c))a      Match: (?!b) succeedsac     Match: (?!b) succeedsab     No match: (?!b(?!c)) failsabe    No match: (?!b(?!c)) failsabc    Match: (?!b(?!c)) succeeds最后一个例子是双重否定:它允许b后面跟一个c。嵌套的负前瞻变为正前瞻:c应该存在。在每个示例中,仅a匹配。前瞻仅是一个条件,不会添加到匹配的文本中。

海绵宝宝撒

环顾四周可以嵌套。所以这个正则表达式匹配“Drupal的6.14 /”是不是后面是“地王” 不跟着“/ all”或“/默认”。令人困惑?使用不同的词,我们可以说它与“ drupal-6.14 /”匹配,然后不跟“ sites”,除非再跟“ / all”或“ / default”

慕虎7371278

如果您这样修改正则表达式:drupal-6.14/(?=sites(?!/all|/default)).*             ^^...然后,它将匹配所有包含的内容drupal-6.14/,sites然后是或以外的其他 所有内容。例如:/all/defaultdrupal-6.14/sites/foodrupal-6.14/sites/bardrupal-6.14/sitesfoo42drupal-6.14/sitesall更改?=为?!匹配您的原始正则表达式将简单地抵消那些匹配:drupal-6.14/(?!sites(?!/all|/default)).*             ^^所以,这只是意味着drupal-6.14/现在不能被跟随sites,随后以外的任何 /all或/default。因此,现在,这些输入将满足正则表达式:drupal-6.14/sites/alldrupal-6.14/sites/defaultdrupal-6.14/sites/all42但是,从其他一些答案(可能还有您的问题)中可能看不出来的是,您的正则表达式也将允许其他输入,drupal-6.14/后面紧跟其他内容sites。例如:drupal-6.14/foodrupal-6.14/xsites结论:因此,您的正则表达式基本上说要包括其名称以或以外的其他子目录开头的所有子目录。drupal-6.14 sitesalldefault
打开App,查看更多内容
随时随地看视频慕课网APP