Unix - 使用egrep查找名称

Unix - 使用egrep查找名称

我正在尝试编写一个egrep脚本来区分一组txt文件中的名称(首字母大写的单词,例如国家/地区、人名等)。我想忽略数字并选择所有大写单词,仅选择单词,不包括句子开头的单词(因此,在“.”之后)也欢迎其他推荐模式

输入示例可以是:

自 1800 年代以来,公众一直对火星上是否有水感兴趣。 1877 年,当火星几乎尽可能接近地球时(距离地球仍然相当遥远,有 5600 万公里),意大利天文学家乔瓦尼·夏帕雷利 (Giovanni Schiaparelli) 观测到了这颗红色星球。他绘制了他所看到的表面特征的地图,包括看起来像渠道网络的东西。

输出将是:

Earth
Giovanni
Italian
Mars
Planet
Red
Schiparelli

答案1

一种方法是 i) 删除所有换行符,以便整个字符串是一个长字符串,并且您可以避免匹配其前面的句号位于上一行的句子的第一个单词,并且 ii) 找到其第一个字母的所有单词是大写且其前面的字符不是., ?,之一!。例如:

$ tr '\n' ' ' < file | grep -Po '(?<![.!?]) \K[A-Z]\w+' 
Mars
Mars
Earth
Italian
Giovanni
Schiaparelli
Red
Planet

并删除重复的条目:

$ tr '\n' ' ' < file  | grep -Po '(?<![.!?]) \K[A-Z]\w+' | sort -u
Earth
Giovanni
Italian
Mars
Planet
Red
Schiaparelli

tr用空格替换换行符。该-P开关打开 Perl 兼容正则表达式 (PCRE) 支持,为我们提供了正在使用的高级功能。意思-o是“仅打印该行的匹配部分”。

正则表达式使用消极回顾( (?>!foo)) 以确保我们只匹配除?!.、空格、大写字母[A-Z]和一个或多个单词字符之外的任何内容。

请注意,如果出现以下情况,这将失败:

  • 名称是文件的第一个单词;
  • 名字是句子的第一个单词;
  • 如果您有像 María de Quinto 这样的复合名称,它将匹配MaríaQuinto会跳过de.

如果您grep不支持-P-o选项,您可以使用 Perl 代替:

perl -0lne 'print join "\n",(/(?<![.!?]) \K[A-Z]\w+/g)' file | sort -u

相关内容