我有一个脚本,它接受用户输入的字符串。我想检查字符串输入是否应该恰好有 2 个点。相关性仅与点有关。字符串不应以点开头和结尾。不应有连续的点。
这是我正在使用的模式:
^[^\.]*\.[^\.]*\.[^\.]*$
这是我正在寻找的字符串:
abc.def.xyz
但在上面的模式中,如果点在前面或末尾,那么该字符串就会被选中 - 这是我不想要的。字符串中应该只有两个点。
不想要的:
.abc.xyz # no dot at the start
abc.xyz. # no dot at the end
abc.def.ced.xyz # only two dots not more than that
我一开始就尝试使用(?!\.)
for 点,但没有成功。
答案1
您并没有说明用户如何输入字符串,但请注意,如果它可能包含换行符,则无法使用grep
过滤它们(除非您使用--null
扩展名),因为grep
一次只处理一行。另请注意,[^\.]
正则表达式匹配除反斜杠和以外的字符,.
并且许多正则表达式实现中的.
正则表达式运算符(或[...]
)不会匹配在区域设置中不形成有效字符的字节。
在这里,要检查$string
包含 2 个且仅 2 个点,但不在开头或结尾且不彼此相邻,您可以使用标准sh
:
case $string in
(*.*.*.* | .* | *. | *..* ) echo not OK;;
(*.*.*) echo OK;;
(*) echo not OK;;
esac
或者使用 ksh glob,可以通过执行以下操作在 bash shell 中使用 ksh glob 的子集shopt -s extglob
:
case $string in
( +([!.]).+([!.]).+([!.]) ) echo OK;;
(*) echo not OK;;
esac
bash
还可以=~
在其[[...]]
ksh 样式构造中与运算符进行扩展正则表达式匹配,但同样,您需要将语言环境修复为 C:
regex_match_in_C_locale() {
local LC_ALL=C
[[ $1 =~ $2 ]]
}
if regex_match_in_C_locale "$string" '^[^.]+\.[^.]+\.[^.]+$'; then
echo OK
else
echo not OK
fi
POSIXly,您可以使用该expr
实用程序进行基本的正则表达式匹配:
if
LC_ALL=C expr "x$string" : 'x[^.]\{1,\}\.[^.]\{1,\}\.[^.]\{1,\}$' > /dev/null
then
echo OK
else
echo not OK
fi
或与awk
实用程序匹配的扩展正则表达式:
regex_match_in_C_locale() {
LC_ALL=C awk -- 'BEGIN {exit(ARGV[1] !~ ARGV[2])}' "$@"
}
if regex_match_in_C_locale "$string" '^[^.]+\.[^.]+\.[^.]+$'; then
echo OK
else
echo not OK
fi
答案2
我认为您正在寻找这个正则表达式^[^.]\+\.[^.]\+\.[^.]\+$
,在这个例子中我们将使用grep
:
括号内的字符按字面意思处理(除了-
),因此不需要转义点。
$ echo ".a.b.c." | grep "^[^.]\+\.[^.]\+\.[^.]\+$"
$ echo ".a.b.c" | grep "^[^.]\+\.[^.]\+\.[^.]\+$"
$ echo "a.b.c." | grep "^[^.]\+\.[^.]\+\.[^.]\+$"
$ echo "a..c" | grep "^[^.]\+\.[^.]\+\.[^.]\+$"
$ echo "a.b.c" | grep "^[^.]\+\.[^.]\+\.[^.]\+$"
a.b.c
正则表达式说
- 该字符串必须以一个或多个非点字符开头,后跟一个点
^[^.]\+\.
,再后跟一个或多个非点字符[^.]\+\.
,再后跟一个或多个非点字符,[^.]\+$
直到行尾。
答案3
在 awk 中,我们可以这样做:
$ awk ' $0"." ~ /^([^.]+\.){3}$/ ' file
a.b.c
abc.def.xyz
添加一个点最后,使模式重复,仅三次not-dot
后跟dot
.喜欢A。--b.--C。或者abc。--定义。--XYZ。
或者,用正则表达式的说法:([^.]\.){3}
仅当正则表达式可以匹配整行时才接受。
答案4
如果您想在 bash 中执行此操作,这是一种方法:
IFS="." read -ra words <<<"$input"
if ((${#words[@]} == 3)) && [[ $input != .* && $input != *. ]]; then
echo "valid input"
fi
这实际上使用了words数组中的值:
IFS="." read -ra words <<<"$input"
# 3 dot-separated fields, and the first and last cannot be empty
if ((${#words[@]} == 3)) && [[ -n ${words[0]} && -n ${words[2]} ]]; then
echo "valid input"
fi