如何使用正则表达式来匹配末尾没有特定字符串的模式

如何使用正则表达式来匹配末尾没有特定字符串的模式

如何使用“POSIX BRE”或“POSIX ERE”正则表达式来匹配字符串(行或单词)不是bak到底有没有?

我想做一个来查找文件名末尾ls | egrep '<regex>'没有的所有文件。bak

例如,如果存在三个文件file1file2_bak、 和bak_file3,则正则表达式应仅匹配file1bak_file3(但不匹配file2_bak)。

我知道可以使用 来完成此操作ls | grep -v 'bak$',但我想在不使用or-v选项的情况下执行此操作。我不想使用,因为这只是 POSIX 正则表达式的理论/学术问题。grepegrep-v

bak这就是我匹配末尾的文件名的方式:

$ ls | egrep 'bak$'
file2_bak
$ 

上面的正则表达式匹配末尾bak$有的所有字符串。bak但是我怎样才能编写一个匹配所有字符串的正则表达式不是 bak在最后?

答案1

如果您使用ksh(或bash扩展的通配符激活,或zshksh 球体启用)您可以仅使用文件通配模式来实现所需的功能:

ls -d -- !(*bak)

对于grep,要得到一个简单的解决方案,只需使用否定-v

ls | grep -v 'bak$'

答案2

常规语言(即“这可以与 RE 匹配”)在补语下封闭,因此这是可能的,但对于实际目的来说并不是很有用:您开始的是条件

最后一个字母是kAND 之前的字母是aAND 之前的字母是b

(让我s[-1]=='k' and s[-2]=='a' and s[-3]=='b'以Python式的方式写)所以一个失败的字符串有

not(s[-1]=='k' and s[-2]=='a' and s[-3]=='b')

IE

not(s[-1]=='k') or not (s[-2]=='a' and s[-3]=='b'))

IE

not(s[-1]=='k') or not(s[-2]=='a') or not(s[-3]=='b')

应用德摩根规则两次,当然,如果你的字符串长度为 2 或更小,情况尤其如此,所以你大致会得到

grep '^$\|^.$\|^..$\|..[^k]$\|.[^a].$\|[^b]..$'

我认为它可以打字但无法维护。

(理论旁注:一般来说,您可以将正则表达式转换为确定性有限自动机 (DFA),反转其中的终端状态,然后将新的 DFA 转换回正则表达式,这都是明确定义的,但是有点乏味且容易出错的过程。)

答案3

使用find

find . -maxdepth 1 -type f ! -name "*bak"
  • .:断言在当前工作目录中搜索
  • -maxdepth 1:断言仅搜索指定目录下一级(即仅当前工作目录)
  • -type f:断言仅搜索文件
  • ! -name "*bak":断言仅搜索不以以下结尾的文件名bak

但是,如果您想要 的grep ls输出:

ls | grep -v 'bak$'
  • -v:仅打印与给定正则表达式不匹配的行

正则表达式分解:

  • bak: 匹配一个bak字符串
  • $: 匹配行尾

使用负向后查找(对于PCREs 兼容grep版本)也是如此:

ls | grep -P '(?<!bak)$'
  • -PPCRE:使用s匹配行

正则表达式分解:

  • (?<!bak):如果前面没有字符串,则仅匹配以下bak模式
  • $: 匹配行尾

答案4

如果您有 Perl 扩展,则可以使用负向前查找。

grep -P '^.{0,2}$|^.*(?!bak)...$'

用于匹配不以 bak 结尾的行

相关内容