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

Time:11-23

I want to exclude any files ending with '.ses' or files with no extension using the following regex pattern. It works fine in command line but not in a shell (bash/ksh).

Regex pattern: "\\\.(?!ses\$)([^.] \$)"

File name examples:

"/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

it returns "true" but "false" in the shell. Anyone knows why?

CodePudding user response:

I would just use a case statement with suitable globs:

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

I would use an array instead of doing whitespace gymnastics.

CodePudding user response:

You can reverse your logic and fail all strings that contain .ses at the end or do not contain a dot after the last /.

Then, you can use 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="true"
  else
    Match_Result="false"
  fi
  echo $Match_Result
done;

Output:

true
false
false
true

Details:

  • ( - start of a capturing group:
    • /[^/.] - / and then one or more chars other than / and .
  • | - or
    • \.ses - .ses
  • ) - end of grouping
  • $ - end of a string.

A case insensitive version is enabled with shopt -s nocasematch/shopt -u nocasematch (see Case insensitive regex in Bash).

  • Related