使用reg表达式从字符串中拉出两个单独的单词?

时间:2010-03-29 21:37:43

标签: .net regex

我需要改进我正在使用的正则表达式。目前,这是:

^ [A-ZA-Z \ S / - +

我用它来从各种配方字符串中提取药物名称,例如:

  • SULFAMETHOXAZOLE-TRIMETHOPRIM 200-40 MG / 5ML PO SUSP
  • AMOX TR / PTRASSIUM CLAVULANATE 125 mg-31.25 mg口服片,可用
  • AMOXICILLIN TRIHYDRATE 125 mg口服片,可用
  • AMOX TR / PTRASSIUM CLAVULANATE 125 mg-31.25 mg口服片,可用
  • 阿莫西林1000MG /克拉维酸盐62.5MG延长释放片

这些示例的结果匹配是:

  • 磺胺甲恶唑 - 甲氧苄啶
  • AMOX TR / POTASSIUM CLAVULANATE
  • AMOXICILLIN TRIHYDRATE
  • AMOX TR / POTASSIUM CLAVULANATE
  • 阿莫西林

前四个是我想要的,但在第五个,我真的需要“阿莫西林/克拉维酸”。

如果缺少像“MG / 5 ML”这样的模式(第一行),我怎样才会抽出像“阿莫西林/克拉维拉”这样的模式(第五行)?

更新

感谢大家的帮助。以下是一个较长的示例列表,其中包含更多细微差别:

  • 阿莫西林1000MG /克拉维酸盐62.5MG延长释放片
  • 阿莫西林1000MG /克拉维酸盐62.5MG延长释放片
  • 阿莫西林10 MG / ML口服混悬液
  • Amoxil 10 MG / ML口服混悬液
  • AMOXICILLIN TRIHYDRATE 125 mg口服片,可用
  • 阿莫沙平
  • AMOX TR / PTRASSIUM CLAVULANATE 125 mg-31.25 mg口服片,可用
  • AMOXICILLIN TRIHYDRATE 125 mg口服片,可用
  • AMOX TR / PTRASSIUM CLAVULANATE 125 mg-31.25 mg口服片,可用
  • AMOX TR / PTRASSIUM CLAVULANATE 125 mg-31.25 mg口服片,可用
  • CARBATROL 200 MG PO CP12
  • CARBATROL 200 MG PO CP12
  • CARBATROL
  • CARBAMAZEPINE 100 MG PO CHEW
  • CEFDINIR 250 MG / 5ML PO SUSR
  • AMOXICILLIN 400 MG / 5ML PO SUSR
  • SULFAMETHOXAZOLE-TRIMETHOPRIM 200-40 MG / 5ML PO SUSP
  • DIAZEPAM 2 MG PO TABS
  • 地西泮
  • PREDNISONE 20 MG PO TABS
  • AUGMENTIN 250-62.5 MG / 5ML PO SUSR
  • ACETAMINOPHEN 325 MG / 10.15ML PO SUSP

我现在所做的是:

    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;
        }
    }

这很丑陋,而且我想通过它运行更多数据时它可能会失败,但它适用于我上面列出的大量案例。

5 个答案:

答案 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;
   }
}