如何找到一个被剥离 non-ASCII 个字符的字符串副本
How to find string copies where one was stripped of non-ASCII characters
我有一个 table 的书名 - 大多数书名都重复多次以用于不同的版本。许多标题被错误地导入,缺少 non-ASCII 个字符,即 "La métamorphose" 变成 "La m?tamorphose" 有时 é 变成 space 或者只是从字符串中删除。
table
editionid | bookid | title
--------------------------------------------
1 | 1 | Elementarne čestice
2 | 1 | Elementarne ?estice
3 | 1 | Elementarne estice
4 | 1 | Las partículas elementales
5 | 2 | Schöne neue Welt
6 | 2 | Sch ne neue Welt
我想通过剥离 non-ASCII 的书名并与同一本书的其他书名进行比较来识别不正确的书名。如果有匹配,我发现标题有问题。
结果:
o.title (flawed) | e.title (good)
-----------------------------------
Elementarne ?estice | Elementarne čestice
Elementarne estice | Elementarne čestice
Sch ne neue Welt | Schöne neue Welt
table 相当大,但因为我只需要在性能不是关键的情况下执行此操作。
我的做法:
select distinct on (o.editionid) o.title, e.title
from editions o
inner join editions e on (o.bookid = e.bookid)
where o.bookid between 1 and 1000
and e.title !~ '^[ -~]*$' -- only for performance
and ((
e.title like '%Þ%' and (o.title = regexp_replace(e.title, '[Þ]', '?') or o.title = regexp_replace(e.title, '[Þ]', ' ') or o.title = regexp_replace(e.title, '[Þ]', ''))
) or (
e.title like '%ß%' and (o.title = regexp_replace(e.title, '[ß]', '?') or o.title = regexp_replace(e.title, '[ß]', ' ') or o.title = regexp_replace(e.title, '[ß]', ''))
) or (
e.title like '%à%' and (o.title = regexp_replace(e.title, '[à]', '?') or o.title = regexp_replace(e.title, '[à]', ' ') or o.title = regexp_replace(e.title, '[à]', ''))
.
.
.
))
到目前为止还可以,但似乎无法单独添加所有 non-ASCII 个字符。有没有人知道一次涵盖所有 non-ASCII 个字符的更通用的方法?
其次 - 如果两个不同的字符被剥离并且我不知道如何解决它,它就不起作用。
第三个但也许是不可能的 - 通常只有一些 non-ASCII 被转换但不是全部,即 "Weiße Nächte" 变成 "Wei e Nächte" - 如果这些也能被覆盖就太好了。
经过一番摆弄,最终并没有那么难:
select distinct on (o.editionid) o.title as flawed, e.title as good
from editions o
inner join editions e on (o.bookid = e.bookid)
where o.bookid between 0 and 10000
and e.title ~ '[^\x00-\x7F]'
and (
o.title = regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g')
or o.title = regexp_replace(e.title, '[^\x00-\x7F]', ' ', 'g')
)
regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g')
是关键,其中 \x00-\x7F
是所有不在 ASCII 方案中的 Unicode 字符,并且 'g'
继续在同一字符串中搜索更多匹配项。
我有一个 table 的书名 - 大多数书名都重复多次以用于不同的版本。许多标题被错误地导入,缺少 non-ASCII 个字符,即 "La métamorphose" 变成 "La m?tamorphose" 有时 é 变成 space 或者只是从字符串中删除。
table
editionid | bookid | title
--------------------------------------------
1 | 1 | Elementarne čestice
2 | 1 | Elementarne ?estice
3 | 1 | Elementarne estice
4 | 1 | Las partículas elementales
5 | 2 | Schöne neue Welt
6 | 2 | Sch ne neue Welt
我想通过剥离 non-ASCII 的书名并与同一本书的其他书名进行比较来识别不正确的书名。如果有匹配,我发现标题有问题。
结果:
o.title (flawed) | e.title (good)
-----------------------------------
Elementarne ?estice | Elementarne čestice
Elementarne estice | Elementarne čestice
Sch ne neue Welt | Schöne neue Welt
table 相当大,但因为我只需要在性能不是关键的情况下执行此操作。
我的做法:
select distinct on (o.editionid) o.title, e.title
from editions o
inner join editions e on (o.bookid = e.bookid)
where o.bookid between 1 and 1000
and e.title !~ '^[ -~]*$' -- only for performance
and ((
e.title like '%Þ%' and (o.title = regexp_replace(e.title, '[Þ]', '?') or o.title = regexp_replace(e.title, '[Þ]', ' ') or o.title = regexp_replace(e.title, '[Þ]', ''))
) or (
e.title like '%ß%' and (o.title = regexp_replace(e.title, '[ß]', '?') or o.title = regexp_replace(e.title, '[ß]', ' ') or o.title = regexp_replace(e.title, '[ß]', ''))
) or (
e.title like '%à%' and (o.title = regexp_replace(e.title, '[à]', '?') or o.title = regexp_replace(e.title, '[à]', ' ') or o.title = regexp_replace(e.title, '[à]', ''))
.
.
.
))
到目前为止还可以,但似乎无法单独添加所有 non-ASCII 个字符。有没有人知道一次涵盖所有 non-ASCII 个字符的更通用的方法?
其次 - 如果两个不同的字符被剥离并且我不知道如何解决它,它就不起作用。
第三个但也许是不可能的 - 通常只有一些 non-ASCII 被转换但不是全部,即 "Weiße Nächte" 变成 "Wei e Nächte" - 如果这些也能被覆盖就太好了。
经过一番摆弄,最终并没有那么难:
select distinct on (o.editionid) o.title as flawed, e.title as good
from editions o
inner join editions e on (o.bookid = e.bookid)
where o.bookid between 0 and 10000
and e.title ~ '[^\x00-\x7F]'
and (
o.title = regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g')
or o.title = regexp_replace(e.title, '[^\x00-\x7F]', ' ', 'g')
)
regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g')
是关键,其中 \x00-\x7F
是所有不在 ASCII 方案中的 Unicode 字符,并且 'g'
继续在同一字符串中搜索更多匹配项。