【问题标题】:Choosing the right regex expression for coordinates为坐标选择正确的正则表达式
【发布时间】:2021-01-21 12:01:58
【问题描述】:

我有各种格式的坐标,并尝试获得或多或少通用的转换例程。

为此,我尝试使用正则表达式解析字符串的各个元素,并尝试通过它们在字符串中的出现索引来获取度、分和秒的各个信息。

对某些人来说它有效....但并非对所有人都有效。我非常确信我的问题与我对正则表达式的有限理解密切相关。

因此问题是:谁对正则表达式模式有更好的理解并且可以提供帮助?

我试图编译一小段代码来演示这个问题。运行下面的示例显示我得到了前四个和后三个坐标的三个分量。其余的 - 介于两者之间 - 仅提供 2 个组件....

coords = c("-53°30''30.54'",
       "s55°30' 30.54",
       "55°30'30.54n",
       "0°1 0.5S",
       "-0°30'30''s",
       "S55 30 30",
       "-55°30'30''",
       "-55° 30' 30''",
       "-55°   30'   30",
       "-55 sometimes with text rests 30 30''",
       "55°30'30,54S",
       "S55° 30' 30,54",
       "-55° 30' 30.54''"
       )

for (i in 1:length (coords)) {
    pattern   <- gregexpr ("[0-9.]+", coords [i])
    print (as.character (unique (unlist (regmatches (coords [i], pattern)))))
}


<Output>
[1] "53"    "30"    "30.54"
[1] "55"    "30"    "30.54"
[1] "55"    "30"    "30.54"
[1] "0"   "1"   "0.5"
[1] "0"  "30"
[1] "55" "30"
[1] "55" "30"
[1] "55" "30"
[1] "55" "30"
[1] "55" "30"
[1] "55" "30" "54"
[1] "55" "30" "54"
[1] "55"    "30"    "30.54"

下面的正则表达式是一个令人印象深刻的怪物;-) 然而,当坐标格式稍有不同(例如 dec_deg)时,它会出现一些问题。在这种情况下,字符串的第一个或第二个数字没有被正确识别。我刚刚用这样的坐标编制了一个列表:

坐标 = c("-53°30''30.54'", "s55°30' 30.54", "55°30'30.54n", "0°1 0.5S", "-0°30'30''s", "S55 30 30", "-55°30'30''", "-55° 30' 30''", "-55° 30' 30", "-55 有时与文本休息 30 30''", "55°30'30,54S", "S55° 30' 30,54", "-55° 30' 30.54''", "-55.5432 30 30.54", "-55.30.30", "55.555", “55,555S”, "S55,555", "S55.555", "55,555°S", "55.555°", "-55,555", “-55.555”

       )

【问题讨论】:

  • 您的目标到底是什么格式?您可能会绕过自己执行正则表达式并使用 measurements 包的单位转换之类的东西,但这取决于您在解析坐标片段后的目标
  • 不,我知道测量包,我对此不满意。上面列出的代码 sn-p 不是完整的故事。我将需要一个更通用的功能,在那里我可以使用一些更正术语。因此,我需要将第一个/第二个/第三个值分开。我曾经用复杂的解析做过,但必须有一个选项可以用正则表达式来做......
  • 你不需要保留负号或方向(“S”等)?这就是为什么看看你需要对你的输出做什么是有帮助的
  • 我稍后会重新解析字符串以获取减号或 S 或 W 以识别负值。主要问题之一是输入数据格式种类繁多且不受监管。

标签: r regex decimal coordinates dms


【解决方案1】:

我们可以尝试使用regexecregmatches 来精确匹配每行中的三个数字。此处的“数字”定义为整数或带有小数部分的整数(小数点为点或逗号)。

我们可以使用do.call将上面的向量列表输出转换为矩阵。

regex <- "^.*?(-?\\d+(?:[,.]\\d+)?).*?(-?\\d+(?:[,.]\\d+)?).*?(-?\\d+(?:[,.]\\d+)?).*$"
do.call(rbind, lapply(regmatches(coords, regexec(regex, coords)), function(x) x[2:4]))

      [,1]  [,2] [,3]   
 [1,] "-53" "30" "30.54"
 [2,] "55"  "30" "30.54"
 [3,] "55"  "30" "30.54"
 [4,] "0"   "1"  "0.5"  
 [5,] "-0"  "30" "30"   
 [6,] "55"  "30" "30"   
 [7,] "-55" "30" "30"   
 [8,] "-55" "30" "30"   
 [9,] "-55" "30" "30"   
[10,] "-55" "30" "30"   
[11,] "55"  "30" "30,54"
[12,] "55"  "30" "30,54"
[13,] "-55" "30" "30.54"

【讨论】:

  • 相当令人印象深刻的怪物字符串。
【解决方案2】:

stringr 似乎可以正常工作...

library(stringr)
str_extract_all(str_replace_all(coords, ",", "."), "[0-9.\\-]+")

[[1]]
[1] "-53"   "30"    "30.54"

[[2]]
[1] "55"    "30"    "30.54"

[[3]]
[1] "55"    "30"    "30.54"

[[4]]
[1] "0"   "1"   "0.5"

[[5]]
[1] "-0" "30" "30"

[[6]]
[1] "55" "30" "30"

[[7]]
[1] "-55" "30"  "30" 

[[8]]
[1] "-55" "30"  "30" 

[[9]]
[1] "-55" "30"  "30" 

[[10]]
[1] "-55" "30"  "30" 

[[11]]
[1] "55"    "30"    "30.54"

[[12]]
[1] "55"    "30"    "30.54"

[[13]]
[1] "-55"   "30"    "30.54"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-18
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 2016-01-11
    • 2019-05-18
    • 1970-01-01
    相关资源
    最近更新 更多