Search code examples
regexlinuxbashshellksh

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


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?


Solution

  • 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="false"
      else
        Match_Result="true"
      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).