有时会有一系列值后跟一个度量单位。输入将是一个包含数字的文本字符串,后跟要由函数提取的单位。给定一个包含数字后跟单位的文本字符串,以下内容可以将数字和单位提取为嵌套向量:
(def aa ["meter" "kilometer"])
(def bb (clojure.string/join "|" aa))
(def cc (str "(\\d+)\\s*(" bb ")"))
(def dd (re-pattern cc))
(defn foostring [strings]
(into [] (map into [] (map (fn [[_ count unit]] {:count count, :unit unit})
(re-seq dd strings)))))
例如,让我们尝试输入:
(foostring "Today I sprinted 40 meters.")
输出将是:
[[[:count 40] [:unit meter]]]
但是我无法提取一系列数字,后跟一个单位,例如以下示例:
(foostring "Today I sprinted between 80-90 meters.")
该功能将为计数和计量单位选择90。但是,我试图获取单位前面的数字范围。
我认为可以提取此类模式的想法将以“近邻”的形式递归查看。即,函数找到单位,然后在单位的左侧查找数字。在“向左看”的过程中,该功能可能搜索单个数字,例如所提到的例子,数字后跟标点符号,即斜线 - 或一个单词。扩展上一次搜索让我举一个例子:
(foostring "Today I ran between 80 to 90 meters.")
或者,口语
(foostring“有80 80 Yeti穿过森林。”)
虽然Yeti的例子很奇怪,但在写作时,它会捕捉到人们的语音被翻译成文本的想法。可能发生这种情况的一个例子是在引用某人撰写文章的过程中。
答案 0 :(得分:3)
我认为可以提取此类模式的想法将以“近邻”的形式递归查看。
如果你的意思是递归,那么你肯定会离开正则表达式的领域。如果你对表达式不太疯狂,可以使用无上下文的EBNF。
(require '[instaparse.core :as insta])
(def foostring
(insta/parser
"<S> = Expr+
Expr = <Stuff> Number+ {<[' '] [Preposition] [' ']> Number} <' '> Unit <Stuff>;
Bleh = #'[a-z A-Z.,]+';
Stuff = {Bleh}
Preposition = 'between'|'to'|'-';
Unit = 'meter'|'kilometer'|'Yeti'|'sandwiches';
Number = #'[0-9]+'"))
如果您没有单位/介词的设定列表,请定义为例如任何一个字。
(foostring "Today I sprinted 40 meters while eating 2 3 4 sandwiches, running from 80-90 Yeti.")
=>
([:Expr [:Number "40"] [:Unit "meter"]]
[:Expr [:Number "2"] [:Number "3"] [:Number "4"] [:Unit "sandwiches"]]
[:Expr [:Number "80"] [:Number "90"] [:Unit "Yeti"]])
答案 1 :(得分:1)
试试这个:
(?i)(?<lowerBound>\d+)(?:\s*(?:-|to)\s*(?<upperBound>\d+))?\s+(?<unit>meters?|kilometers?|...)
http://fiddle.re/k20ff (选择Java,因为Clojure与Java共享相同的风格)