我有一个小脚本。
#!/bin/bash
# test for regular expressions to match...
DIR="/search/path/"
NAME="FOO[0-9][0-9]_<bar|dog|cat>"
for FILE in `find ${DIR} -maxdepth 1 -type f -name "*\.[dD][oO][cC]"`
do
BASENAME=`basename ${FILE}`
FILENAME="${BASENAME%.*}"
if [[ "${FILENAME}" == ${NAME} ]]
then
echo "Found $FILENAME"
else
echo "$FILENAME not matching..!"
fi
done
在此脚本中,我希望匹配所有以 开头的文件FOO[0-9[0-9]_
,然后是bar
、dog
或cat
。但如果有其他内容,例如bog
或cog
,则car
应该不是匹配。
当我这样做时,[a-z][a-z][a-z]
它们会匹配...
我已经尝试过做类似的事情:
NAME="FOO[0-9][0-9]_(bar|dog|cat)"
or
NAME="FOO[0-9][0-9]_bar|dog|cat"
or
NAME="FOO[0-9][0-9]_[bar|dog|cat]"
or
NAME="FOO[0-9][0-9]_'bar|dog|cat'"
但在有关正则表达式的文档中我找不到完全匹配的内容。
我需要将它放在一行中,因为我使用它的主脚本要复杂得多,并且有很多不同的子进程挂在它上面。
这还有可能吗……?
答案1
仅使用字符串匹配,您需要使用=~
(与扩展正则表达式匹配):
if [[ "${FILENAME}" =~ "FOO[0-9][0-9]_(bar|dog|cat)" ]]
或者
NAME="FOO[0-9][0-9]_(bar|dog|cat)"
if [[ "${FILENAME}" =~ ${NAME} ]]
以匹配您的原始版本。
==
始终是通配符匹配(如果禁用通配符则为精确匹配),它不能与正则表达式一起使用。
或者,如果您可以对脚本进行更多更改,假设您使用的是 GNU find
,则可以使用以下内容进行过滤find
:
find ${DIR} -maxdepth 1 -type f -regextype posix-extended -regex ".*/FOO[0-9][0-9]_(bar|dog|cat)\.[Dd][Oo][Cc]"
(-regextype posix-extended
告诉find
我们要使用扩展正则表达式,正则表达式本身以.*/
because开头-regex
,匹配整个路径,而不仅仅是文件名。)
答案2
不要循环输出find
,而是用来find
执行您使用路径名提供的脚本:
#!/bin/bash
topdir='/search/path'
pattern='FOO[0-9][0-9]_(bar|dog|cat)'
find "$topdir" -type f -maxdepth 1 -iname '*.doc' -exec bash -c '
pattern=$1; shift
for pathname do
stem=$( basename "${pathname%.*}" )
if [[ "$stem" =~ $pattern ]]; then
printf "Found %s\n" "$pathname"
else
printf "No match in %s\n" "$pathname"
fi
done' bash "$pattern" {} +
请注意,使用-iname
withfind
对文件名进行不区分大小写的匹配。
有关的:
或者更简单,使用bash
:
#!/bin/bash
topdir='/search/path'
pattern='FOO[0-9][0-9]_(bar|dog|cat)'
shopt -s globstar nullglob
for pathname in "$topdir"/**/*.[Dd][Oo][Cc]; do
stem=$( basename "${pathname%.*}" )
if [[ "$stem" =~ $pattern ]]; then
printf "Found %s\n" "$pathname"
else
printf "No match in %s\n" "$pathname"
fi
done
或者,在整个过程中使用文件名通配符:
#!/bin/bash
topdir='/search/path'
shopt -s globstar nullglob extglob
for pathname in "$topdir"/**/*FOO[0-9][0-9]_@(bar|dog|cat)*.[Dd][Oo][Cc]
do
printf "Found %s\n" "$pathname"
done
globstar
启用**
glob 模式,其工作方式类似于*
但匹配路径名中的斜杠。nullglob
使不匹配的全局模式扩展到空字符串。extglob
提供一些扩展的全局模式。其中 与@(...)
括号中的任何一种模式相匹配。
对于单行,您可以使用
shopt -s globstar nullglob extglob; printf 'Found %s\n' "$topdir"/**/*FOO[0-9][0-9]_@(bar|dog|cat)*.[Dd][Oo][Cc]
但如果没有找到匹配项,这仍然会打印字符串Found
(单独在一行上)。