通配正则表达式和 Bash

通配正则表达式和 Bash

我只是无法弄清楚我是否应该在 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将会带你到条件构造[[ ... ]]您可以在其中找到及其运算符的描述=~

其他工具如grepfindvimperlfirefox可以在不同的上下文中使用其中之一或两者。他们的文档会告诉你。另请注意,这两种类型的图案都有多种风格。根据经验,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

(其中\zPCRE 相当于 ERE,$如 PCRE$匹配主题末尾但也在主题末尾的换行符之前)。

如果设置rematchpcre选项 ( set -o rematchpcre),[[ =~ ]]则使用 PCRE 而不是 ERE。

相关内容