如何做一个对口音不敏感的Grep? [英] How to do an accent insensitive grep?

查看:0
本文介绍了如何做一个对口音不敏感的Grep?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法使用grep执行不区分重音的搜索,最好保留--COLOR选项?我的意思是grep --secret-accent-insensitive-option aei将匹配?ei,也可能匹配äē?和æi。

我知道我可以使用iconv -t ASCII//TRANSLIT从文本中删除重音符号,但我不知道如何使用它进行匹配,因为文本已转换(它适用于grep-c或-l)

推荐答案

您正在寻找一整串POSIX正则表达式equivalence classes

14.3.6.2等价类运算符([= … =])

    Regex识别列表中的等价类表达式。等价类表达式是一组整理元素,它们都属于同一等价类。通过将排序元素放在开放等价类运算符关闭等价类运算符之间,可以形成等价类表达式。[=表示开放等价类操作符,=]表示闭等价类操作符。例如,如果aA是等价类,则[[=a=]][[=A=]]都将同时匹配aA。如果等价类表达式中的排序元素不是等价类的一部分,则匹配器将该等价类表达式视为排序符号。

我在下一行使用插入符号来表示实际是什么颜色的。我还调整了测试字符串,以说明有关案例的一点。

$ echo "I match àei but also äēì and possibly æi" | grep '[[=a=]][[=e=]][[=i=]]'
I match àei but also äēì and possibly æi
        ^^^          ^^^

这与像aei这样的所有单词匹配。它与æi不匹配这一事实应该提醒您,您受制于您正在使用的regex库中存在的任何映射(假设是gnulib,这是我所链接和引用的),尽管我认为digraphs很可能超出了即使是最好的等价类映射的范围。

不要期望等价类是可移植的,因为它们太神秘了。


更进一步,如果您只想要带重音的字符,事情就复杂得多了。在这里,我已将您对aei的请求更改为[aei]

$ echo "I match àei but also äēì and possibly æi" | grep '[[=a=][=e=][=i=]]'
I match àei but also äēì and possibly æi
^  ^    ^^^     ^    ^^^ ^       ^     ^
清除这一点以避免非重音匹配将需要等价类和前瞻/后视,虽然BRE(基本POSIX正则表达式)和ERE(扩展POSIX正则表达式)支持前者,但它们都缺少后者。Libpcre(grep -P和大多数其他人使用的Perl兼容regex的C库)和perl支持后者,但缺少前者:

尝试#1:grep使用libpcre:失败

$ echo "I match àei but also äēì and possibly æi" 
    | grep -P '[[=a=][=e=][=i=]](?<![aei])'
grep: POSIX collating elements are not supported

尝试#2:perl本身:失败

$ echo "I match àei but also äēì and possibly æi" 
    | perl -ne 'print if /[[=a=][=e=][=i=]](?<![aei])/'
POSIX syntax [= =] is reserved for future extensions in regex; marked by <-- HERE in m/[[=a=][=e= <-- HERE ][=i=]](?<![aei])/ at -e line 1.

尝试#3:python(有自己的PCRE实现):(静默)失败

$ echo "I match àei but also äēì and possibly æi" 
    | python -c 'import re, sys;
                 print re.findall(r"[[=a=][=e=][=i=]]", sys.stdin.read())'
[]
哇,PCRE、python甚至perl不支持的正则表达式功能!这样的情况并不多见。(不要管第二个等价类上的投诉,它仍然只投诉/[[=a=]]/。)这进一步证明等价类是晦涩难懂的。

事实上,似乎没有任何任何PCRE库能够等价类;equivalence classes at regular-expressions.info一节声称只有实现POSIX标准的regex库才真正具有这种支持。GNUgrep最接近,因为它可以执行BRE、ERE和PCRE,但不能组合它们。

所以我们将分两部分进行。

尝试#4:恶心的诡计:成功

$ echo "I match àei but also äēì and possibly æi" 
    | grep --color=always '[[=a=][=e=][=i=]]' 
    | perl -pne "s/e[[0-9;]*me[K(?i)([aei])/$1/g"
I match àei but also äēì and possibly æi
        ^            ^^^

代码审核:

  • grep强制启用颜色,以便perl可以键入颜色代码以记录匹配
  • ${GREP_COLOR:-01;31}备注grep的颜色(默认为相同的大红色)
  • perls///命令匹配完整的颜色代码,然后匹配我们要从最终结果中删除的非重音字母。它用(未着色的)字母替换所有这些字母
  • perl正则表达式中(?i)之后的任何内容都不区分大小写,因为[[=i=]]匹配I
  • perl -p-e执行完成时打印输入的每一行

有关BRE、ERE和PCRE等的详细信息,请参阅this StackExchange regex postPOSIX regexps at regular-expressions.info。有关每种语言的差异(包括libpcre与python PCRE与Perl)的更多信息,请查看tools at regular-expressions.info


2019更新:GNU grep现在使用$GREP_COLORS,它看起来像ms=1;41,优先于较旧的$GREP_COLORLike1;41。这很难提取(并且很难在两者之间进行权衡),所以我修改了Try#4中的Perl代码,以查找anySGR color code,而不是只键入grep将添加的颜色。有关前面的代码,请参阅revision 2 of this answer

我当前无法验证Apple Mac OS X使用的BSD grep是否支持POSIX正则表达式等价类。

这篇关于如何做一个对口音不敏感的Grep?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆