首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个文件中单词的大小写和重音不敏感匹配

两个文件中单词的大小写和重音不敏感匹配
EN

Stack Overflow用户
提问于 2022-02-14 12:30:22
回答 2查看 126关注 0票数 0

我得到了两个未引用和单列 TSV文件(从数据库导出),其中有几千人的名字,我需要找到出现在这两个文件中的名称。这两个文件都是UTF-8CRLF终止的,并从BOM 0xEF 0xBB 0xBF开始。

一个简单的joincomm命令可以完成这个任务,但是名称上有一些不同:

代码语言:javascript
复制
# cat file1.tsv
A.  Einstein
Louis Pasteur 
Diego Armando Maradona
Isaac Newton
 Frava D’onä
D Rüge
Françoise Barré-Sinoussi
代码语言:javascript
复制
# cat file2.tsv
Diego Maradona
Albert Einstein
Francoise, BARRE  SINOUSSI
Louis Pasteur
frava d'ona
Marie-Louise Von FRANZ
Dimitri Rüge

file2.tsv中的预期匹配将是:

代码语言:javascript
复制
Diego Maradona
Albert Einstein
Francoise, BARRE  SINOUSSI
Louis Pasteur
frava d'ona
Dimitri Rüge

我编写了这个bash sed awk grep脚本,它动态地生成匹配姓氏的正则表达式:

代码语言:javascript
复制
#!/bin/bash

# U+0300 = 0xCC80 = 52352
# U+033F = 0xCCBF = 52415
# U+0340 = 0xCD80 = 52608
# U+036E = 0xCDAE = 52654

_COMBINING_CHARS_=()

for i in {52352..52415} {52608..52654}
do
    hex=$(printf %04X "$i")
    _COMBINING_CHARS_+=( "$(printf '\x'"${hex:0:2}"'\x'"${hex:2:2}")" )
done

_COMBINING_CHARS_ERE_=$(IFS='|'; printf %s "${_COMBINING_CHARS_[*]}")
代码语言:javascript
复制
# Function that removes the BOM, CRLF, and COMBINING characters:
sanitize() {
    LANG=C sed -E \
        -e $'1s/^\xEF\xBB\xBF//' \
        -e $'s/\r$//' \
        -e "s/$_COMBINING_CHARS_ERE_//g" \
    -- "$@"
}
代码语言:javascript
复制
# Function that generates a regex for the _lastname_:
toERE() {
    awk '
        {
            if ( $0 ~ /,/) {
                n = split($0, a, ",");
                $0 = a[n];
            } else {
                $0 = $NF
            }
            sub("^[[:space]]+","");
            sub("[[:space]]+$","");
            gsub("[[:space:]-]+"," ");
        }

        {
            ere = ""
            sep = "";
            for ( nf = 1; nf <= NF; nf++ ) {
                n = split($nf, c, "");
                for ( i = 1; i <= n; i++ ) {
                    ere = ere "[[=" c[i] "=]]"
                }
                ere = sep ere 
                sep = "[[:space:]-]+"
            }
            print ere "[[:space:]]*$"
        }
    ' < <(sanitize "$@")
}
代码语言:javascript
复制
grep -E -f <(toERE "$1") <(sanitize "$2")

不幸的是,给定输入的结果是:

代码语言:javascript
复制
grep: illegal byte sequence

UTF-8多字节字符似乎是问题所在,但我想不出用awk来处理它的方法。

EN

回答 2

Stack Overflow用户

发布于 2022-02-14 13:10:14

agrep呢?man agrep:使用近似匹配功能搜索文件中的字符串或正则表达式。这并不完美,我们会看到:

代码语言:javascript
复制
$ while IFS= read -r line
do 
    echo -n "$line: "
    agrep -B -y  "$line" file1
done < file2

输出:

代码语言:javascript
复制
Diego A. Maradona: agrep: 1 word matches within 6 errors
Maradona, Diego Armando
Albert Einstein: agrep: 1 word matches within 5 errors
A. Einstein
Louis Pasteur: Louis Pasteur
frava dona: agrep: 2 words match within 4 errors
Maradona, Diego Armando
Fräva Dona

很好的例子,因为我们已经在最后三行中看到了一个问题。

票数 1
EN

Stack Overflow用户

发布于 2022-02-15 10:03:30

建议采用以下技巧:

代码语言:javascript
复制
 cat file1.csv file1.csv | sort | uniq -d

解释

cat file1.csv file1.csv一个接一个地组合bot文件

sort把相似的线放在一起

uniq -d只打印有重复项的行

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71111940

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档