![正则表达式 括号表达式与 bash](https://linux22.com/image/218694/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%20%E6%8B%AC%E5%8F%B7%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%B8%8E%20bash.png)
我想编写一个正则表达式,仅允许用户输入包含字母数字字符、下划线、句点、破折号和加号的输入。
在 bash 脚本中,我有:
VALID="^[0-9a-zA-Z_\.\-\+]+$"
THE_INPUT=$1
if [[ ! $THE_INPUT =~ $VALID ]]; then
echo "ERROR"
exit 1
fi
为什么当用户输入带有 - 的输入时这不起作用?
用户输入示例:
很棒的食物.png
我。产生错误
很棒的_+食物.png
我。不会产生错误
答案1
[0-9a-zA-Z_\.\-\+]
POSIX Basic 或 Extended 正则表达式中的括号表达式匹配:
0-9
:整理元素(甚至不一定是单个字符!),范围在0
和之间9
(可以是任何内容,具体取决于区域设置,因此不应用于C
/POSIX
区域设置之外的输入验证)a-zA-Z
: 与a
toz
和A
to相同Z
。_\.
:下划线、反斜杠或句点:\-\
\
:整理在和之间排序的元素\
。只是可能\
,但你永远不知道。\+
: 再次反斜杠和+
.
As\
在括号表达式中并不特殊。
要在集合中包含文字-
,需要将其放置在最后或第一个(或^
在否定集合中紧随其后)。
bash 使用 POSIX 扩展正则表达式作为其=~
运算符。
在这里,您想要:
VALID='^[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.+-]+$'
如果可以选择切换到zsh
,您可以使用其扩展的 glob 运算符,它们是扩展正则表达式的超集,具有不同的语法,并且行为不那么令人惊讶,并且可以处理与正则表达式相反的非文本:
set -o extendedglob
VALID='[0-9a-zA-Z_+.-]##'
if [[ $input != $~VALID ]]; then...
(请注意,此处的~
内容$VALID
被视为模式,而不是字面意思)。
它还具有一个[:WORD:]
字符类,alnum
与区域设置中分类的任何字符以及 中的字符相匹配$WORDCHARS
。
在 C 语言环境中,您可以定义WORDCHARS='.-+_'
然后使用:
set -o extendedglob # needed for ##, the equivalent of ERE +.
VALID='[[:WORD:]]##'
zsh
还支持 PCRE,PCRE 也有括号表达式,这并不令人意外:
zmodload zsh/pcre
VALID='^[0-9a-zA-Z._+-]+\z'
if [[ ! $input -pcre-match $VALID ]]; then...
或者=~
使用 PCRE 而不是 ERE:
set -o rematchpcre
VALID='^[0-9a-zA-Z._+-]+\z'
if [[ ! $input =~ $VALID ]]; then...
你也可以VALID='^[0-9a-zA-Z\-._+]+\z'
在那里使用。
请注意,PCRE 不支持 UTF-8 以外的多字节字符集,并且如果$input
UTF-8 无效,则上述内容会报告 UTF-8 语言环境中的错误。
在 C 语言环境中,您还可以使用VALID='^[\w.+-]\z'
, 其中\w
匹配alnum
s 和下划线。
¹ awk 是一个例外,因为它确实使用扩展的正则表达式,但\
在括号表达式或中仍然是特殊的至少在某些实现中是这样。
答案2
通常在正则表达式中,-
字符类块中的字符暗示一个范围(例如[a-z]
。表达您是的常用方式不是暗示范围的意思是将连字符放在字符类描述符的最末尾。当我在你的脚本中这样做时,它似乎按你的意愿工作:
VALID="^[0-9a-zA-Z_\.\+\-]+$"
因此:
$ ./741634.sh parameter/with/slashes
ERROR
$ ./741634.sh parameter-with-dashes
$