从给定字符串中提取任意位置的可行性?

时间:2012-08-17 10:31:19

标签: perl dictionary awk machine-learning nlp

我有许多电子表格,其中包含旅行信息等。

我需要提取行描述旅行的起点和终点位置,以及行中的一两件事,但这些额外字段应该不重要。

没有所有位置的已知列表,也没有固定的文本模式,我可以找到的只是位置名称。

我正在搜索的字段有0-2个位置,有时位置有别名。

问题

如果我们有这个:

00229 | 445 | RTF | Jan   |  trn_rtn_co  | Chicago to Base1 
00228 | 445 | RTF | Jan   |  train       | Metroline to home coming from Base1
00228 | 445 | RTF | Jan   |  train_s     | Standard train journey to Friends
例如,我(虽然它会有所不同),我想要这个:

RTF|Jan|Chicago   |Base1
RTF|Jan|Home      |Base1
RTF|Jan|NULL      |Friends

然后继续,查看Base1Friends对该人(其唯一ID为RTF)的意义,并将其替换为合理的位置(假设他们只有一组'朋友' “):

RTF|Jan|Chicago   |Rockford
RTF|Jan|Home      |Rockword
RTF|Jan|NULL      |Milwaukee

我需要什么

我需要一种从最后一列中挑选关键词的方法,例如: Metroline来自Base1

我正在寻找三种类型的词:

  1. 家庭位置
    这些已知且有限,我可以从列表中获取
  2. 家庭别名
    这些已知且有限,我可以从列表中获取
  3. 离开地点
    这些未知但是英国的城市/城镇等我不知道如何在字符串中识别这些。这是我的主要问题
  4. 我的想法

    我去的程序我想到的是awk,但我不知道我是否可以可靠地搜索找到位置名称使用专有名词(即位置)的位置。

    是否有标准位置的包,库或字典?

    我可以获得一个程序来搜索电子表格并“学习”位置名称吗?

    这似乎已经解决了一个问题(即在一串文本中找到单词),但我不确定我在做什么,而且我只是一个新手程序员。

    对我所能做的任何帮助都将不胜感激。

    编辑:

    任何答案,例如“US_Locations_Cities是您可以检查的内容”,“使用...检查awk文件中提到的字符串”,“有一个语言X库,可让程序学会识别位置名称,它不是RegEx,但它可能有效“或”有一个位置名称字典这里“会没事的。

    最终任何帮助我做我想做的事情(即获取位置名称!)都会非常棒。

3 个答案:

答案 0 :(得分:3)

很抱歉告诉你,但我认为这不是100%可编程的。 最好的办法是定义一些标准搜索:

  • 芝加哥到Base1
    [WORD]到[WORD]:
    其中“to”是固定的,你在前后找到一个单词。之前的单词是你的目标之后的来源和单词

  • 来自Base1的Metroline回家 [WORD]来自[WORD]来自[WORD]: “to”和“from from”的地方是固定的,你在适当的位置寻找三个单词。

如果您可以匹配来源和目标 - > OK
如果你无法匹配某些东西,那么就为该行抛出一个错误,让用户决定甚至更好地实现适当的修正,让程序自动重新评估该行。

这些都是非平凡的目标。 考虑:

  • 我们的城市
  • 非英文文本条目
  • 缩写

自动纠错尝试将找到的[WORD]与我们或其他城市的列表相匹配。 如果找不到城市则会抛出错误。如果您发现该错误要么将未找到的城市包含在您的城市列表中,要么以公开(官方)名称翻译城市名称。

答案 1 :(得分:1)

我建议的最好方法是,只要您的所在地都是美国城市,就可以使用this one等邮政编码数据库。

我不知道您希望任何程序如何选择FriendsBase1

等内容

答案 2 :(得分:1)

我必须同意hacktick 现在的情况,它不可编程。似乎唯一的解决方案是发明一种语言或协议。

我认为一个简单的实现如下:

  1. 在这种语言中,您有两个关键字:tofrom(您也可以将at分配为from的关键字synoym。
  2. 这些关键字定义了作为“扫描区域”的字符串的一部分 识别名字
  3. 我只打算实施最简单的扫描,但正如帖子末尾所示,您可以进行后备。

    1. 在实现中,您有一个“首选名称”哈希,您可以在其中定义要在其中显示的内容显示的名称。

      { Base1   => 'Rockford'
      , Friends => 'Milwaukee'
      , ...
      }
      
    2. 您可以使用以下规则通过关键字之间的文本块split {/ 1}}句子:

      一个。第一个块,如果不是关键字,则被视为'from'的值。 A.在此或任何后续块上,如果是关键字,则保存下一个块    在之后为该值。 答:在存储之前,每个值都被“扫描”一个首选短语    作为价值。

      my @chunks 
          = grep {; defined and ( s/^\s+//, s/\s+$//, length ) } 
            split /\b(from|to)\s+/i, $note
          ;
      my %parts = ( to => '', from => '' );
      my $key;
      do { 
          last unless my $chunk = shift @chunks;
          if ( $key ) { 
              $parts{ $key } = $preferred_title{ $chunk } // $chunk;
              $key = '';
          }
          elsif ( exists $parts{ lc $chunk } ) { 
              $key = lc $chunk;
          }
          elsif ( !$parts{from} ) { 
              $parts{from} = $preferred_title{ $chunk } // $chunk;
          }
      } while ( @chunks );
      say join( '|', $note, @parts{ qw<from to> } );
      
    3. 至少,收集这些价值并将其打印出来可以为您提供筛选以决定进一步的行动方案。这将告诉您'home coming'被视为“来自”声明,以及'Standard train journey'

      你*可以通过修改正则表达式来修复'home coming'

       /\b(?:(?:coming )?(from)|(to))\s+/i
      

      我们可以将以下键值对添加到preferred_title哈希:

      home => 'Home'
      

      我们可以简单地定义'Standard train journey' => '',或者我们可以创建拒绝模式列表,如果它们符合模式,我们会拒绝字符串作为有意义的值。

      但是它们允许您转储值列表并优化数据扫描。另一个想法是,因为看起来你的地方使用大写字母(除了'家')非常一致。因此,我们可以通过将块与

      匹配来增加找到正确字符串的几率
      /\b(home|\p{Upper}.*)/
      

      请注意,这仍然会将'Standard train journey'视为正确的位置。所以这仍然需要通过拒绝规则处理。

      我在此重申,这可以是一种扫描数据的最小方法,使您可以了解该系统作为位置所需的内容以及“80/20”它:这就是希望这些规则处理80%的情况,你可以调整算法来处理剩下的20%的80%,并迭代到你最不需要改变一些条目的程度。

      然后,您有一个规范,从那时起您需要遵循创建旅行笔记。您甚至可以在输入时扫描注释并发出类似信息 “在笔记中找不到目的地!”。