![匹配零个或多个以逗号分隔的关键字](https://linux22.com/image/216303/%E5%8C%B9%E9%85%8D%E9%9B%B6%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E4%BB%A5%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E7%9A%84%E5%85%B3%E9%94%AE%E5%AD%97.png)
我想匹配零个或多个用逗号分隔的关键字的可能性。
我使用以下正则表达式
if [[ "$var" =~ ^([^,]+(,[^,]+)*)*$ ]]; then
echo "KY MATCH"
fi
我想匹配以下内容
var=""
var="keyword"
var="keyword,keyword"
var="keyword,keyword,keyword"
正则表达式可以简化或更清晰吗?
答案1
Bash 使用 POSIX 扩展正则表达式 - try info bash -n 'Conditional Constructs'
and man 7 regex
(对于第一个命令,您需要安装info
,对于第二个命令man-pages
)。
如果您的关键字仅包含字母,您可以使用[:alpha:]
字符类,也可以使用[:alnum:]
or [:word:]
。
尝试这个脚本并选择正确的类:
#!/bin/bash
for var in "" "keyword" "keyword,keyword" "keyword,keyword,keyword"; do
[[ "$var" =~ ^([[:alpha:]]+,?)*$ ]] && echo "$var" MATCHES || echo "$var" DOES NOT MATCH
done
for var in "1" "key word" "key123word,keyword" "keyword, keyword ,keyword"; do
[[ "$var" =~ ^([[:alpha:]]+,?)*$ ]] && echo "$var" MATCHES || echo "$var" DOES NOT MATCH
done
更新
正如评论中所说,我的表达方式不适用于此 - keyword,keyword,
。这个表达方式似乎很合适^([[:alpha:]]+(,[[:alpha:]]+)*)*$
——我不明白如何让它变得更简单。
答案2
如果将逗号分隔的关键字转换为如下的正则表达式,则可以更容易:
#!/usr/bin/env -S bash -
#keywords="keyword"
#keywords="aaa,bbb,ccc"
keywords="aaa,bbb,ccc,"
#keywords="ddd,"
#keywords=""
var='aaa'
regex="${keywords%,}" # trim trailing ','
regex="${regex//,/\|}" # replace ',' with '|'
printf 'Your var : %s\n' "$var"
printf 'Your regex: %s\n' "$regex"
if [[ $var =~ ^($regex)$ ]]; then
printf '%s\n' '-> it matches'
else
printf '%s\n' '-> it does not match'
fi
这导致
$ temp/match-comma-separated-keywords.sh
Your var: aaa
Your regex: aaa|bbb|ccc
-> it matches
答案3
看起来您想要排除的唯一内容是空,
分隔字段,但没有字段的特殊情况除外,因此排除,
第一个或最后一个或有两个连续字符串的字符串,因此:
case $string in
(,* | *,,* | *,) echo>&2 not OK;;
(*) echo OK;;
esac
或者
case ,${string:-empty}, in
(*,,*) echo>&2 not OK;;
(*) echo OK;;
esac
这是标准 POSIX sh 语法,或使用 Korn 风格的语法:
[[ ,${string:-empty}, != *,,* ]]
。不需要=~
。
一个正则表达式可能是:
[[ $string, =~ ^([^,]+,)*$ ]]
不过,您可以使用通配符模式来完成此操作,而不必求助于系统的正则表达式引擎以及可能随之而来的问题(例如它因非字符而窒息):
[[ $string, = *(+([^,]),) ]]