我需要改进我正在使用的正则表达式。目前,这是:
^ [A-ZA-Z \ S / - +
我用它来从各种配方字符串中提取药物名称,例如:
这些示例的结果匹配是:
前四个是我想要的,但在第五个,我真的需要“阿莫西林/克拉维酸”。
如果缺少像“MG / 5 ML”这样的模式(第一行),我怎样才会抽出像“阿莫西林/克拉维拉”这样的模式(第五行)?
更新
感谢大家的帮助。以下是一个较长的示例列表,其中包含更多细微差别:
我现在所做的是:
private static string GetMedNameFromIncomingConceptString(string conceptAsString)
{
// look for match at beginning of string
Match firstRegMatch = new Regex(@"^[a-zA-Z\s/-]+").Match(conceptAsString);
if (firstRegMatch.Success)
{
// grab matching part of string as whole string
string firstPart = conceptAsString.Substring(firstRegMatch.Index, firstRegMatch.Length);
// look for additional match following a hash (like Amox 1000 / Clav 50)
Match secondRegMatch = new Regex(@"/\s[a-zA-Z\s/-]+").Match(conceptAsString, firstRegMatch.Length);
if (secondRegMatch.Success)
return firstPart + conceptAsString.Substring(secondRegMatch.Index, secondRegMatch.Length);
else
return firstPart;
}
else
{
return conceptAsString;
}
}
这很丑陋,而且我想通过它运行更多数据时它可能会失败,但它适用于我上面列出的大量案例。
答案 0 :(得分:1)
当斜线是剂量的一部分时,它是否总是紧跟一个数字?如果是这样,这个正则表达式应该适合你:
([A-Z]\D+)\d[^/]*(?:/\d[^/]*)*
它会像其他人建议的那样主动匹配剂量信息,但仅捕获药物名称。然后对$1
进行全局替换以删除剂量。以下是我在Java中测试它的方法:
String[] data = {
"SULFAMETHOXAZOLE-TRIMETHOPRIM 200-40 MG/5ML PO SUSP",
"AMOX TR/POTASSIUM CLAVULANATE 125 mg-31.25 mg ORAL TABLET, CHEWABLE",
"AMOXICILLIN TRIHYDRATE 125 mg ORAL TABLET, CHEWABLE",
"AMOX TR/POTASSIUM CLAVULANATE 125 mg-31.25 mg ORAL TABLET, CHEWABLE",
"Amoxicillin 1000 MG / Clavulanate 62.5 MG Extended Release Tablet"
};
Pattern p = Pattern.compile("([A-Z]\\D+)\\d[^/]*(?:/\\d[^/]*)*");
Matcher m = p.matcher("");
for (String s : data)
{
System.out.println(m.reset(s).replaceAll("$1"));
}
输出:
SULFAMETHOXAZOLE-TRIMETHOPRIM
AMOX TR/POTASSIUM CLAVULANATE
AMOXICILLIN TRIHYDRATE
AMOX TR/POTASSIUM CLAVULANATE
Amoxicillin / Clavulanate
编辑:好的,看起来剂量中的斜线总是跟在ML
后面,后面可能有一个数字,可能包括一个小数点。此外,剂量信息可能完全缺失。这个正则表达式似乎为扩展的样本输入产生了期望的结果:
([A-Z]\D+)(?:$|\d[^/]*(?:/[\d.]*ML[^/]*)*)
它也应该在C#中工作。
答案 1 :(得分:0)
你所要求的是无法做到的,因为任何这样做的尝试都会导致“PO SUSP”,“ORAL TABLET”等。我建议你做的就是尝试两个化合物和剂量,然后去除剂量。
答案 2 :(得分:0)
我认为你最好不要删除你知道不会成为药物名称一部分的单词,例如oral
,数字等。这应该会让你得到你想要的东西。
或者,如果您有一个药物数据库,您只能从该数据库中提取单词,这应该只为您提供药物。
我意识到这些解决方案不使用正则表达式,但我认为它们不能完成您为它们设置的任务。
答案 3 :(得分:0)
你的正则表达式的问题在于它遇到一个数字后就会停止匹配。假设一旦你有剂量,你就完成了。但是,第五个例子反驳了这个假设。
如果您考虑使用正则表达式,请考虑以下问题:您如何解释为常规Joe提取药物的规则?像“任何和所有字符串包含字母或字符/和 - ,除了单词mg,ml,口头,扩展,释放,平板电脑,chewable,po,susp。”听起来很难,因为它可能并未涵盖所有情况。
如果示例代表您的数据,我确实看到了一种模式。假设Perl:
/($compound+ $dosage)+ $usage/xi
,其中
$compound = qr/[a-z-] [\s\/]?/x;
$dosage = qr/(\/? [\d.-] \s (ml|mg))+/x; # add measurement units if needed
$usage = qr/.*/; # rest of string
如果你问我,并且我没有测试它,那么非常毛茸茸,只证明它是正确的。它可能需要一些调整。
编辑:我看到您添加了标记.net
,但正则表达式在C#中看起来类似。
答案 4 :(得分:0)
查看新数据,最简单,最明确,最健壮的方法是首先删除用法(平板电脑,可咀嚼,怀疑),然后删除剂量。
private static string GetMedNameFromIncomingConceptString(string conceptAsString) {
Regex compoundsAndDosages = new Regex(@".*[\s\d]m[gl]", RegexOptions.IgnoreCase);
Regex onlyDosage = new Regex(@"\s?[\d.-]+\s?m[gl][\/-]?", RegexOptions.IgnoreCase);
// keep compounds and dosage (= remove usage)
Match cad = compoundsAndDosages.Match(conceptAsString);
if (cad.Success) {
// remove dosages (= keep compunds)
return onlyDosage.Replace(cad.Value, "");
} else {
return conceptAsString;
}
}