緯度/経度座標を照合するための正規表現を作成しようとしています。私が使用した倍精度数を照合する(\-?\d+(\.\d+)?)
ために、それを単一の式に組み合わせようとしました:
^(\-?\d+(\.\d+)?),\w*(\-?\d+(\.\d+)?)$
これはダブル、コンマ、おそらくスペース、および別のダブルに一致すると期待していましたが、機能しないようです。具体的には、1つ以上ではなく、スペースがない場合にのみ機能します。何が悪いのでしょうか?
緯度/経度座標を照合するための正規表現を作成しようとしています。私が使用した倍精度数を照合する(\-?\d+(\.\d+)?)
ために、それを単一の式に組み合わせようとしました:
^(\-?\d+(\.\d+)?),\w*(\-?\d+(\.\d+)?)$
これはダブル、コンマ、おそらくスペース、および別のダブルに一致すると期待していましたが、機能しないようです。具体的には、1つ以上ではなく、スペースがない場合にのみ機能します。何が悪いのでしょうか?
回答:
空白は\ sではなく\ sです
^(-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)$
これが機能するかどうかを確認します
これは、正しい範囲内にある緯度と経度の値に厳密に一致します。
^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$
一致する
一致しない
?:
非キャプチャグループ構文とキャプチャ極性を使用して、キャプチャグループの緯度のみを取得するようにこれを変更し、極性をキャプチャしました(^[-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))$
私はこれらのものを使用しています(10進形式、6桁の10進数):
^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,6})?))$
^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,6})?))$
ここにも、アクセスを容易にするために両方をテストする要点があります。これはJava TestNGテストです。実行するには、Slf4j、Hamcrest、Lombokが必要です。
import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Test;
@Slf4j
public class LatLongValidationTest {
protected static final String LATITUDE_PATTERN="^(\\+|-)?(?:90(?:(?:\\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\\.[0-9]{1,6})?))$";
protected static final String LONGITUDE_PATTERN="^(\\+|-)?(?:180(?:(?:\\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\\.[0-9]{1,6})?))$";
@Test
public void latitudeTest(){
DecimalFormat df = new DecimalFormat("#.######");
df.setRoundingMode(RoundingMode.UP);
double step = 0.01;
Double latitudeToTest = -90.0;
while(latitudeToTest <= 90.0){
boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
assertThat(result, is(true));
latitudeToTest += step;
}
latitudeToTest = -90.1;
while(latitudeToTest >= -200.0){
boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
assertThat(result, is(false));
latitudeToTest -= step;
}
latitudeToTest = 90.01;
while(latitudeToTest <= 200.0){
boolean result = df.format(latitudeToTest).matches(LATITUDE_PATTERN);
log.info("Latitude: tested {}. Result (matches regex): {}", df.format(latitudeToTest), result);
assertThat(result, is(false));
latitudeToTest += step;
}
}
@Test
public void longitudeTest(){
DecimalFormat df = new DecimalFormat("#.######");
df.setRoundingMode(RoundingMode.UP);
double step = 0.01;
Double longitudeToTest = -180.0;
while(longitudeToTest <= 180.0){
boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
assertThat(result, is(true));
longitudeToTest += step;
}
longitudeToTest = -180.01;
while(longitudeToTest >= -300.0){
boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
assertThat(result, is(false));
longitudeToTest -= step;
}
longitudeToTest = 180.01;
while(longitudeToTest <= 300.0){
boolean result = df.format(longitudeToTest).matches(LONGITUDE_PATTERN);
log.info("Longitude: tested {}. Result (matches regex): {}", df.format(longitudeToTest), result);
assertThat(result, is(false));
longitudeToTest += step;
}
}
}
実際には、正規表現の上にあるAlix Axelは、緯度、経度の範囲の観点では間違っています。
緯度の測定範囲は–90°〜+ 90°経度の測定範囲は–180°〜+ 180°
したがって、以下の正規表現はより正確に検証されます。
また、私の考えに従って、緯度/経度の小数点を制限するべきではありません。
^([-+]?\d{1,2}([.]\d+)?),\s*([-+]?\d{1,3}([.]\d+)?)$
またはObjective C
^([-+]?\\d{1,2}([.]\\d+)?),\\s*([-+]?\\d{1,3}([.]\\d+)?)$
99
がLatitude
、99
範囲外の-90, +90
ため無効です。
^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$
正規表現の内訳:
^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$
-?
#負の値を受け入れる
^
#文字列の開始
[0-9]{1,3}
#1〜3桁に一致(例:0〜999)
(?:
#一致してみてください...
\.
#小数点
[0-9]{1,10}
#1から10桁が続く(つまり0-9999999999)
)?
#...オプションで
$
#文字列の終わり
これを試して:
^(\()([-+]?)([\d]{1,2})(((\.)(\d+)(,)))(\s*)(([-+]?)([\d]{1,3})((\.)(\d+))?(\)))$
それをチェックしてください:
上のボックスに式を貼り付け、次に下のボックスに次のようなものを配置します。
(80.0123, -34.034)
(80.0123)
(80.a)
(980.13, 40)
(99.000, 122.000)
正規表現の内訳:
^ # The string must start this way (there can't be anything before).
(\() # An opening parentheses (escaped with a backslash).
([-+]?) # An optional minus, or an optional plus.
([\d]{1,2}) # 1 or 2 digits (0-9).
( # Start of a sub-pattern.
( # Start of a sub-pattern.
(\.) # A dot (escaped with a backslash).
(\d+) # One or more digits (0-9).
(,) # A comma.
) # End of a sub-pattern.
) # End of a sub-pattern.
(\s*) # Zero or more spaces.
( # Start of a sub-pattern.
([-+]?) # An optional minus, or an optional plus.
([\d]{1,3}) # 1 to 3 digits (0-9).
( # Start of a pattern.
(\.) # A dot (escaped with a backslash).
(\d+) # One or more digits (0-9).
)? # End of an optional pattern.
(\)) # A closing parenthesis (escaped with a backkslash).
) # End of a pattern
$ # The string must end this way (there can't be anything after).
さて、これが行わないことは、それ自体をこの範囲に制限することです:
(-90 to +90, and -180 to +180)
代わりに、それ自体がこの範囲に制限されます。
(-99 to +99, -199 to +199)
しかし、ポイントは主に表現の各部分を分解することです。
これはより厳密なバージョンです:
^([-+]?\d{1,2}[.]\d+),\s*([-+]?\d{1,3}[.]\d+)$
-90
-+90
-180
-+180
@ macro-ferrari私はそれを短縮する方法を見つけました、そして正規表現エンジンに関する最近のすべての話に照らして先読みなしで
const LAT_RE = /^[+-]?(([1-8]?[0-9])(\.[0-9]{1,6})?|90(\.0{1,6})?)$/;
const LONG_RE = /^[+-]?((([1-9]?[0-9]|1[0-7][0-9])(\.[0-9]{1,6})?)|180(\.0{1,6})?)$/;
緯度と経度の正しいパターンをチェックするための目的Cの完全で単純な方法は次のとおりです。
-( BOOL )textIsValidValue:(NSString*) searchedString
{
NSRange searchedRange = NSMakeRange(0, [searchedString length]);
NSError *error = nil;
NSString *pattern = @"^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: pattern options:0 error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:searchedString options:0 range: searchedRange];
return match ? YES : NO;
}
ここで、searchedStringは、ユーザーがそれぞれのテキストフィールドに入力する入力です。
PHPのバージョンは次のとおりです(入力値は:$latitude
と$longitude
):
$latitude_pattern = '/\A[+-]?(?:90(?:\.0{1,18})?|\d(?(?<=9)|\d?)\.\d{1,18})\z/x';
$longitude_pattern = '/\A[+-]?(?:180(?:\.0{1,18})?|(?:1[0-7]\d|\d{1,2})\.\d{1,18})\z/x';
if (preg_match($latitude_pattern, $latitude) && preg_match($longitude_pattern, $longitude)) {
// Valid coordinates.
}
あなたはこれを試すことができます:
var latExp = /^(?=.)-?((8[0-5]?)|([0-7]?[0-9]))?(?:\.[0-9]{1,20})?$/;
var lngExp = /^(?=.)-?((0?[8-9][0-9])|180|([0-1]?[0-7]?[0-9]))?(?:\.[0-9]{1,20})?$/;
これを試して:
^[-+]?(([0-8]\\d|\\d)(\\.\\d+)?|90(\\.0+)?)$,\s*^[-+]?((1[0-7]\\d(\\.\\d+)?)|(180(\\.0+)?)|(\\d\\d(\\.\\d+)?)|(\\d(\\.\\d+)?))$
これを試して:
(?<!\d)([-+]?(?:[1-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*([-+]?(?:180(?:\.0+)?|(?:(?:1[0-7]\d)|(?:[1-9]?\d))(?:\.\d+)?))(?!\d)`