我只是无法弄清楚我是否应该在 bash 中使用通配符或正则表达式。我关于 bash shell 脚本的书特别令人困惑,因为它没有澄清这个主题,而且我最终也没有得到正确的理解。让我举个例子,它说明如下:... . (点)字符表示“任何单个字符”。因此,ac 匹配所有abc、aac、aqc 等。
好吧,太好了,我认为他错了,因为这是正则表达式,但我做的第一件事就是测试它:
$ touch abc aac aqc
$ ls
aac abc aqc
$ ls a.c
ls: cannot access 'a.c': No such file or directory
然后我去谷歌搜索,发现了这篇名为“通配教程”的帖子,我在想,对吧,就是这个。
https://linuxhint.com/bash_globbing_tutorial/
我几乎立即认为这都是错误的,因为他的“通配符”有一半是通过 grep 完成的,它使用不通配符的 BRE。例如他指出:
“$用于定义结束符”
这是错误的,因为这是正则表达式的含义,并且它不是通配符。所以我测试一下:
$ ls
aac abc aqc
$ ls c$
ls: cannot access 'c$': No such file or directory
所以他在谷歌上的排名第一的点击链接也是错误的。就好像书本或在线上都没有帖子澄清这个主题,所以我需要一些帮助来定义正则表达式和通配符之间的区别,并具有一定的绝对确定性。
答案1
使用正则表达式的唯一地方bash
是=~
其[[ ... ]]
构造的运算符,在这种情况下它是 POSIX 扩展正则表达式:
if [[ abc =~ ^a.b$ ]]; then
echo 'abc matches the ^a.b$ ERE'
fi
其他地方:
case abc in (a?b) echo 'abc matches the a?b glob pattern'; esac
[[ abc = a?b ]] && echo 'abc matches the a?b glob pattern'
printf '%s\n' a?b
:实际的通配符又名文件名生成又名路径名扩展printf '%s\n' "${var#a?b}" "${var%a?b}" "${var##a?b}" "${var%%a?b}" "${var/a?b/x}
compgen -G 'a?b'
(与 相同complete
)。help 'r??d'
这就是 shell 通配符,又名 glob 模式,又名文件名/fnmatch 模式。
运行info bash pattern
以专门了解 bash 中的内容。info -n conditional bash
将会带你到条件构造[[ ... ]]
您可以在其中找到及其运算符的描述=~
。
其他工具如grep
、find
、vim
、perl
、firefox
可以在不同的上下文中使用其中之一或两者。他们的文档会告诉你。另请注意,这两种类型的图案都有多种风格。根据经验,glob 模式通常用于匹配文件名(如 shell 中的 glob 或find
's -name
/ -path
),而 regexp 则用于任意文本匹配。
ksh93 是一个可以在其 glob 中使用正则表达式(基本、扩展、类 Perl 或增强)的 shell:
$ printf '%s\n' ~(E:^a.b$)
a=b
axb
在 zsh 中,您可以通过 glob 限定符在其 glob 中使用正则表达式(扩展或 pcre)e
:
$ printf '%s\n' *(e['[[ $REPLY =~ "^a.b$" ]]'])
a=b
axb
$ zmodload zsh/pcre
$ printf '%s\n' *(e['[[ $REPLY -pcre-match "^a.b\z" ]]'])
a=b
axb
(其中\z
PCRE 相当于 ERE,$
如 PCRE$
匹配主题末尾但也在主题末尾的换行符之前)。
如果设置rematchpcre
选项 ( set -o rematchpcre
),[[ =~ ]]
则使用 PCRE 而不是 ERE。