我对 Unix 比较陌生,我偶然发现了一个好奇心。一些 shell 结构(如case
or find
)采用模式匹配,但它并不完全是正则表达式。其他命令,如 ed
、sed
、vi
和awk
使用正则表达式进行模式匹配。有人可以列出哪些 shell 命令(内置命令、程序)使用正则表达式,哪些使用其他类型的模式匹配吗?
答案1
答案2
我认为使用正则表达式的主要区别在于它们是否需要匹配整个字符串。在case
、find
和其他一些 bash 命令中,您必须匹配整个字符串,而在sed
、awk
等中grep
,您必须匹配字符串的任何部分。除此之外,它们很相似,但当然并不完全相同。
例如,当您在case
bash shell 的语句中使用正则表达式时,假定您的正则表达式描述了整个字符串。即(我正在使用例子在这里)
case $SERVER in
db-[0-9]+\.host\.com) echo "DB server"
;;
*)echo "Unknown server"
;;
esac
可以看到db-[0-9]+.host.com描述的是字符串,以“db-”开头,然后有一位或多位数字,最后以“.host.com”结尾,所以db-1 .host.com 将匹配,而 xdb-1.host.com 将不匹配。
现在,如果您查看sed
,并以类似的方式编写搜索模式
echo "xdb-1.host.com"| sed -nr '/db-[0-9]+\.host\.com/p'
sed
与case
命令不同,将打印 xdb-1.host.com 行,因为它可以在该字符串中找到搜索模式。因此,我们的想法不是匹配整个字符串,而是找到该模式的任何出现。
类似地,如果您在find
命令中使用正则表达式,则整个字符串必须匹配。例如,
find / -regextype sed -regex ".*\.dat"
将找到所有扩展名为 dat 的文件。但如果您尝试使用 进行相同的搜索sed
,
find / | sed -nr '/.*\.dat/'
它将匹配文件名中包含字符串“.dat”的所有文件。
当然,还有一些细微的语法差异。例如,如果你这样做
find / -name "*.dat"
这也是一种正则表达式,其中*表示“任意数量的任意符号”,但严格意义上的正则表达式你应该写“.*”,其中“.”表示任意符号,* 表示任意数量的“.”类型的符号,因此一起表示任意数量的任意符号。