use*_*107 13 bash regular-expression wildcards
我在当前路径有 3 个目录。
$ls
a_0db_data a_clean_0db_data a_clean_data
$ls a_*_data
a_0db_data:
a_clean_0db_data:
a_clean_data:
$ls a_[a-z]*_data
a_clean_0db_data:
a_clean_data:
Run Code Online (Sandbox Code Playgroud)
我希望最后一个 ls 命令只匹配a_clean_data. 为什么它也匹配包含0?
bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)
Run Code Online (Sandbox Code Playgroud)
Seb*_*ian 29
该[a-z]部分是不是有什么号码相匹配; 这是*. 您可能会混淆 shell globbing和正则表达式。
诸如grep接受各种风格的正则表达式之类的工具(默认情况下是基本的,-E用于扩展的,-P用于Perl 正则表达式)
例如(-v反转匹配)
$ ls a_[a-z]*_data | grep -v "[0-9]"
a_clean_data
Run Code Online (Sandbox Code Playgroud)
如果您想使用 bash 正则表达式,这里有一个关于如何测试变量$ref是否为整数的示例:
re='^[0-9]+$'
if ! [[ $ref =~ $re ]] ; then
echo "error"
fi
Run Code Online (Sandbox Code Playgroud)
uml*_*ute 21
所以问题是:为什么a_[a-z]*_datamatch a_clean_0db_data?
这可以分为四个部分:
a_匹配开头a_clean_0db_data,留下clean_0db_data待匹配
[a-z]匹配范围内的任何字符a-z(例如c),留待lean_0db_data匹配
* 匹配任意数量的字符,例如 lean_0db
_data 匹配尾随 _data
在正则表达式中,[a-z]*表示a..z 范围内的任意数量的字符(包括零),但您正在处理 shell globbing,而不是正则表达式。
如果你想要正则表达式,一些find实现有一个-regex谓词:
find . -maxdepth 1 -regex "^.*/a_[a-z]*_data$"
Run Code Online (Sandbox Code Playgroud)
在-maxdepth这里只是限制搜索结果你在该文件夹的正则表达式的匹配整个文件名,所以我添加了一个^.*/到路径部分匹配
Sté*_*las 11
*在 shell 模式中匹配 0 个或多个字符。不要与*正则表达式运算符混淆,这意味着前面的 atom 有 0 个或多个。
*在基本的 shell 模式中没有与 regexp 等效的东西。但是,各种 shell 对此都有扩展。
ksh有*(something):
ls a_*([a-z])_data
Run Code Online (Sandbox Code Playgroud)您可以在bashwithshopt -s extglob或zshwith中使用相同的内容setopt kshglob:
shopt -s extglob
ls a_*([a-z])_data
Run Code Online (Sandbox Code Playgroud)在zsh与extendedglob启用,#是相当于正则表达式*:
setopt extendedglob
ls a_[a-z]#_data
Run Code Online (Sandbox Code Playgroud)在 的最新版本中ksh93,您还可以在 glob 中使用正则表达式。这里有扩展的正则表达式:
ls ~(E:a_[a-z]*_data)
Run Code Online (Sandbox Code Playgroud)请注意,[a-z]根据当前语言环境匹配不同的东西。它通常只匹配语言环境中的 26a到z拉丁非重音字母C。在其他语言环境中,它通常匹配更多,并不总是有意义。要匹配您的语言环境中的字母,您可能更喜欢[[:alpha:]].