如何使用“POSIX BRE”或“POSIX ERE”正则表达式来匹配字符串(行或单词)不是bak
到底有没有?
我想做一个来查找文件名末尾ls | egrep '<regex>'
没有的所有文件。bak
例如,如果存在三个文件file1
、file2_bak
、 和bak_file3
,则正则表达式应仅匹配file1
和bak_file3
(但不匹配file2_bak
)。
我知道可以使用 来完成此操作ls | grep -v 'bak$'
,但我想在不使用or-v
选项的情况下执行此操作。我不想使用,因为这只是 POSIX 正则表达式的理论/学术问题。grep
egrep
-v
bak
这就是我匹配末尾的文件名的方式:
$ ls | egrep 'bak$'
file2_bak
$
上面的正则表达式匹配末尾bak$
有的所有字符串。bak
但是我怎样才能编写一个匹配所有字符串的正则表达式做不是有 bak
在最后?
答案1
答案2
常规语言(即“这可以与 RE 匹配”)在补语下封闭,因此这是可能的,但对于实际目的来说并不是很有用:您开始的是条件
最后一个字母是
k
AND 之前的字母是a
AND 之前的字母是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
字符串$
: 匹配行尾
使用负向后查找(对于PCRE
s 兼容grep
版本)也是如此:
ls | grep -P '(?<!bak)$'
-P
PCRE
:使用s匹配行
正则表达式分解:
(?<!bak)
:如果前面没有字符串,则仅匹配以下bak
模式$
: 匹配行尾
答案4
如果您有 Perl 扩展,则可以使用负向前查找。
grep -P '^.{0,2}$|^.*(?!bak)...$'
用于匹配不以 bak 结尾的行