最も移植性が高く、最も簡単に記述でき、最も保守しやすいのは、部分的に行うことです。
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
これは、有効な IP アドレスのみに一致し、さらに検査するために各部分を分割します
if (int(group[1]) != 224 and (int(group[1]) != 0 or int(group[2]) != 0 or int(group[3]) != 0 or int(group[4]) != 0) ...
正規表現は、「しかしそうではない」操作が得意ではありません。
ただし、それを単一の正規表現として使用することを主張する場合は、有効なオプションをすべて列挙してください。
\b(25[0-5]|2[0134][0-9]|22[0-35-9]|1[0-9][0-9]?|[2-9][0-9]|[2-9])
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
...最初のオクテットが 224 または 0 でないことをテストするだけなので、これは完璧ではありません。0.0.0.0 に対する完全なテストが必要な場合は、少なくとも 1 つのオクテットは非ゼロです。
そしてもちろん、40 億の組み合わせすべてに対して正しい答えを返すことを確認するテストを作成する必要があります。実行に時間がかかりすぎてはいけません... ;-)