为什么正则表达式在 bash/ksh 中不起作用,而在命令行中却可以正常工作

Why Regex doesn't work in bash/ksh while it works fine in command line

我想使用以下正则表达式模式排除任何以“.ses”结尾的文件或没有扩展名的文件。它在命令行中工作正常,但在 shell (bash/ksh).

中不行

正则表达式模式:"\.(?!ses$)([^.]+$)"

文件名示例:

"/test/path/test file with spaces.__1" (expected true)
"/test/path/test file with spaces.ses" (expected false)
"/test/path/test file with spaces" (expected false)
"/test/path/test file with spaces.txt" (expected true)
FILE_NAME="/test/path/test file with spaces.__1"

PATTERN_STR="\.(?!ses$)([^.]+$)"

if [[ "${FILE_NAME}" =~ ${PATTERN_STR} ]]; then

        Match_Result="true"
else

        Match_Result="false"

fi

echo $Match_Result

它 returns 是“真”,但 shell 是“假”。有人知道为什么吗?

我只会使用带有合适 glob 的 case 语句:

case "${FILE_NAME##*/}" in
*.ses)
    Match_Result=false
    ;;
*.*)
    Match_Result=true
    ;;    
*)
    Match_Result=false
    ;;
esac

考虑使用数组而不是做空白体操。

您可以反转您的逻辑,让所有末尾包含 .ses 或在最后一个 /.

后不包含点的字符串都失败

然后,你可以使用this script:

#!/bin/bash
declare -a arr=("/test/path/test file with spaces.__1"
"/test/path/test file with spaces.ses"
"/test/path/test file with spaces"
"/test/path/test file with spaces.txt")
# true false false true
PATTERN_STR='(/[^/.]+|\.ses)$'
for FILE_NAME in "${arr[@]}"; do
  if [[ "$FILE_NAME" =~ $PATTERN_STR ]]; then
    Match_Result="false"
  else
    Match_Result="true"
  fi
  echo $Match_Result
done;

输出:

true
false
false
true

详情:

  • ( - 捕获组的开始:
    • /[^/.]+ - / 然后是 /.
    • 以外的一个或多个字符
  • | - 或者
    • \.ses - .ses
  • ) - 分组结束
  • $ - 字符串结尾。

使用 shopt -s nocasematch/shopt -u nocasematch 启用不区分大小写的版本(参见 )。