正则表达式在bash if-else块的条件下不能按预期工作

时间:2017-04-01 20:07:54

标签: regex bash if-statement

我在if-else块中定义匹配的模式是:

php artisan cache:clear
php artisan config:clear
php artisan view:clear

在我的脚本中,我正在接收需要与模式匹配的用户输入,如果不匹配,则会显示相应的错误消息。很简单,但给我一个艰难的时间。我在脚本中的代码块是:

pat="17[0-1][0-9][0-9][0-9].AUG"
nln=""

我希望用户输入要输入的文件名的格式为:

echo "How many days' AUDIT Logs need to be searched?"
read days
echo "Enter file name(s)[For multiple files, one file per line]: "
for(( c = 0 ; c < $days ; c++))
do
  read elements
  if [[  $elements =~ $pat ]];
     then
       array[$c]="$elements"
  elif [[  $elements =~ $nln ]];
     then
        echo "No file entered.Run script again. Exiting"
        exit;
  else
      echo "Invalid filename entered: $elements.Run script again. Exiting"
      exit;
  fi
done

所以基本上yymmdd.AUG(y年,月,日),尾随或前导空格都可以。除此之外的任何内容都应该抛出170402.AUG 消息。另外,我想检查一下如果它是一个带有“回车”命中的空行,它应该会出错"Invalid filename entered: $elements.Run script again. Exiting"

然而,我的代码,即使我输入类似“xxx”的文件名,应该抛出"No file entered.Run script again. Exiting",实际上是对空行检查为true,并抛出"Invalid filename entered: $elements.Run script again. Exiting"

需要一些帮助来处理正则表达式的用户输入检查,否则我的脚本的其余部分工作正常。

2 个答案:

答案 0 :(得分:3)

我认为正如评论中所讨论的那样,您对 glob 匹配和regEx匹配感到困惑,您定义为pat的是一个需要的全局匹配等同于==运算符,

pat="17[0-1][0-9][0-9][0-9].AUG"
string="170402.AUG"

[[ $string == $pat ]] && printf "Match success\n"

等效~匹配将是

pat="17[[:digit:]]{4}\.AUG"
[[ $string =~ $pat ]] && printf "Match success\n"

正如您所看到的,正则表达式语法中的.已被转义为剥夺其特殊含义(匹配任何字符),但仅用作文字点。带有字符数POSIX的{​​{1}}字符类[[:digit:]]可让您匹配{4}后跟4

的数字

对于字符串空检查,请按照Cyrus或Benjamin.W的评论建议

.AUG

(或)

[[ $elements == "" ]]

答案 1 :(得分:2)

我不会用how many days(想要数15天或类似的人)来欺骗用户?另外,为什么每行只有一个文件?你应该帮助用户,而不是像微软那样弄错他们......

首先:

show_help() { cat <<'EOF'
bla bla....
EOF
}

show_files() { echo "${#files[@]} valid files entered: ${files[@]}"; }

while read -r -p 'files? (h-help)> ' line
do
    case "$line" in
        q) echo "quitting..." ; exit 0 ;;
        h) show_help ; continue;;
        '') (( ${#files} )) && show_files; continue ;;
        l) show_files ; continue ;;
        p) (( ${#files} )) && break || { echo "No files enterd.. quitting" ; exit 1; } ;; # go to processing
    esac
    # select (grep) the valid patterns from the entered line
    # and append them into the array
    # using the -P (if your grep know it) you can construct very complex regexes
    files+=( $(grep -oP '17\d{4}.\w{3}' <<< "$line") )
done

echo "processing files ${files[@]}"

使用这样的逻辑,您可以构建功能强大且用户友好的应用程序。此外,您可以-e使用read启用readline功能(光标键等)......

但是 :)考虑只创建一个接受参数的简单脚本。没有任何对话等。例如:

myscript -h

与上述相同,或更长的帮助文本

myscript 170402.AUG 170403.AUG 170404.AUG 170405.AUG

将对文件做任何事情。主要的好处是,你可以在文件名中使用globbing,比如

myscript 1704*

依旧......

如果你真的想要这个对话框,它可以在没有任何参数的情况下运行脚本时显示它,例如:

myscript

将以交互模式运行......