一个将文件名与正则表达式匹配的行?

一个将文件名与正则表达式匹配的行?

我有一个小脚本。

#!/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]_,然后是bardogcat。但如果有其他内容,例如bogcog,则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" {} +

请注意,使用-inamewithfind对文件名进行不区分大小写的匹配。

有关的:

或者更简单,使用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(单独在一行上)。

相关内容