是否可以使用正则表达式匹配条件?

时间:2013-12-10 13:07:41

标签: regex vim

我在super user发布了此问题,建议我在stackoverflow上发布此问题。

我真的很喜欢vim,今天我遇到了有趣的问题,我认为可以通过regexp完成,但我不能形成正确的问题。

我有一个非常大的sql文件。它整合了许多不同的查询。文件包含以下内容:

select * from hr.employees, oe.orders, oe.order_items
select * from hr.employess, oe.orders, hr.job_history
select * from oe.customers, oe.orders, hr.employees
select * from hr.employees, hr.departments, hr.locations

如何仅选择与该行只有hr.匹配的那些行?例如,上面它将是第一行和第三行。

4 个答案:

答案 0 :(得分:5)

当然,可以匹配这些线。这种模式匹配:

^\%(\%(hr\.\)\@!.\)*hr\.\%(\%(hr\.\)\@!.\)*$

有些人喜欢使用非常神奇的开关\v来减少反斜杠的数量。然后相同的模式变为

\v^%(%(hr\.)@!.)*hr\.%(%(hr\.)@!.)*$

(这里我使用了非捕获括号\%(...\),但捕获括号\(...\)也可以正常工作。)

问题是:你想用这些线做什么?删除它们?

在这种情况下,您可以使用:global命令:

:g/\v^%(%(hr\.)@!.)*hr\.%(%(hr\.)@!.)*$/d

的更多信息
  • :h :global
  • :h /\v
  • :h /\%(
  • :h /\@!

答案 1 :(得分:3)

检查行是否仅包含hr.使用正则表达式

的单次出现 带有^(?=.*\bhr\.)(?!.*\bhr\..*\bhr\.).*修饰符的

m。我建议使用grep -P实用程序。

Regular expression visualization

答案 2 :(得分:3)

为此,您需要将负向lookbehind 否定先行断言相结合;即,当前匹配的模式在同一行之前或之后不得匹配。在Vim中,这些原子的原子分别是\@<!\@!

因此,找到一次X的模式就是:

/\%(X.*\)\@<!X\%(.*X\)\@!/

应用于您的模式hr.

/\%(hr\..*\)\@<!hr\.\%(.*hr\.\)\@!/

答案 3 :(得分:0)

像这样的问题我总是觉得更容易将它分成正则表达式的多种用法。如果我要用grep过滤这个,我会这样做:

grep "hr\." foo.sql

这给了我所有的行“hr。”,甚至是带有两个的行。

现在我再次通过grep管道输出并要求它忽略hr.出现两次的行:

grep "hr\." foo.sql | grep -v "hr\..*hr\."

我知道你在谈论vim,但我正在展示可能有用的替代品,可能会更清楚。