Bash Regex - 文字列はドットで始まり、終わらないでください。

Bash Regex - 文字列はドットで始まり、終わらないでください。

ユーザーの文字列入力を受け入れるスクリプトがあります。文字列入力に正確に2つの点があることを確認したいと思います。相関関係は単にポイントに関するものです。文字列はドットで始まり終わらないでください。連続した点があってはなりません。

これが私が使用するパターンです:

^[^\.]*\.[^\.]*\.[^\.]*$

これが私が探している文字列です:

abc.def.xyz

ただし、上記のパターンで点が前後にある場合は、文字列が選択されます。これは望ましくありません。文字列には2つの点しか含まれていません。

不要:

.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 dotsを試してみましたが、成功しませんでした。

答え1

ユーザーが文字列を入力する方法は明らかではありませんが、改行が含まれている場合は一度に1行だけ処理するため(拡張子を使用しない限り)grepフィルタリングできません。また、正規表現はバックスラッシュおよびを除く文字と一致し、多くの正規表現実装の正規表現演算子(または)は、ロケールで有効な文字を形成しないバイトと一致しません。--nullgrep[^\.]..[...]

ここで2つの点があることを確認するには、$string開始または終了ではなく、互いに隣接していないことを確認するには、次の基準を使用できますsh

case $string in
  (*.*.*.* | .* | *. | *..* ) echo not OK;;
  (*.*.*) echo OK;;
  (*) echo not OK;;
esac

または、ksh globを使用して次の手順を実行して、bashシェルで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

正規表現は言う

  • 文字列は、1つ以上の非ドット文字で始まり、その後にドット、^[^.]\+\.1つ以上のドット以外の文字[^.]\+\.、次に1つ以上のドット以外の文字が行の[^.]\+$終わりに来る必要があります。

答え3

awkでは、次のことができます。

$ awk '  $0"."  ~   /^([^.]+\.){3}$/  ' file

a.b.c
abc.def.xyz

1つ追加指す最後にパターンを繰り返し、3回だけフォローnot-dotしますdotㅏ。-雨。-氏。またはアルファベット。-定義。-XYZ。

または正規表現の用語で言うと、次のようになります。([^.]\.){3}

正規表現が行全体と一致できる場合にのみ許可されます。

答え4

Bashでこれを行うには、次の1つの方法に従ってください。

IFS="." read -ra words <<<"$input"
if ((${#words[@]} == 3)) && [[ $input != .* && $input != *. ]]; then
    echo "valid input"
fi

これは実際には単語配列の値を使用します。

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

関連情報