Bash Regex - 字符串不应以点开头和结尾

Bash Regex - 字符串不应以点开头和结尾

我有一个脚本,它接受用户输入的字符串。我想检查字符串输入是否应该恰好有 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

相关内容