如何在文件搜索中使用 soundex 搜索?

如何在文件搜索中使用 soundex 搜索?

我有一个包含许多文件的目录。而且,我忘记了确切的文件名。因此,当我想查找文件时却找不到它。

如果有任何使用 soundex 算法进行搜索的工具对我的情况有帮助。

答案1

这是出于我自己的好奇心而写的答案。您可能应该根据“的答案中的建议构建一些东西是否有一个 Unix 命令可以主要根据发音时的发音来搜索相似的字符串?“(PerlText::Soundex模块)而不是使用它。


以下 shell 脚本和附带sed脚本在命令行上给定搜索字符串的情况下,在以当前目录为根的目录树中执行 Soundex 文件名搜索。

$ sh soundex.sh fissbux
./fizzbuzz
./fizzbuzz.c
./fizzbuzz2
./fizzbuzz2.c

$ sh soundex.sh sharlok
./HackerRank/Algorithms/02-Implementation/17-sherlock_and_squares.c

$ sh soundex.sh sundek
./soundex.sh
./soundex.sed

shell 脚本 ( soundex.sh):

#!/bin/sh

soundex=$( printf '%s\n' "$1" | tr 'a-z' 'A-Z' | sed -f soundex.sed )

find . -exec bash -c '
    paste <( printf "%s\n" "${@##*/}" | tr "a-z" "A-Z" | sed -f soundex.sed ) \
          <( printf "%s\n" "$@" ) |
    awk -vs="$0" "\$1 == s" | cut -f 2-' "$soundex" {} +

该脚本使用脚本(如下)计算搜索词的 soundex 值sed。然后,它用于find查找当前目录或以下目录中的所有名称,并以与搜索词相同的方式计算每个名称的 soundex 值。如果文件名的 soundex 值与搜索项匹配,则打印该文件的完整路径。

我承认shell脚本有点基础。例如,可以通过在soundex.sed脚本中添加绝对路径来改进。正如现在所写的,它要求sed脚本位于当前目录中。它也不支持包含换行符的文件名。

剧本sedsoundex.sed):

s/[^[:alpha:]]//g
h
s/^\(.\).*$/\1/
x
y/bfpvBFPVcgjkqsxzCGJKQSXZdtDTlLmnMNrR/111111112222222222222222333344555566/
s/\([1-6]\)[hwHW]\1/\1/g
s/\([1-6]\)\1\1*/\1/g
s/[aeiouyhwAEIOUYHW]/!/g
s/^.//
H
x
s/\n//
s/!//g
s/^\(....\).*$/\1/
s/^\(...\)$/\10/
s/^\(..\)$/\100/
s/^\(.\)$/\1000/

这实现了“American Soundex”如维基百科所述。它不会修改初始字符(如果不是字母则删除它),这就是为什么我tr在 shell 脚本中将字符串大写。

这尚未经过彻底测试,但似乎可以正确处理维基百科文章中提到的名称。

带注释的版本(“步骤”指的是上述维基百科文章中的步骤):

# Remove non-alphabetic characters
s/[^[:alpha:]]//g

# STEP 1 (part 1: retain first character)

# Save whole line in hold-space
h

# Delete everything but the first character and swap with hold-space
s/^\(.\).*$/\1/
x

# The hold-space now contains only the first character

# STEP 2

y/bfpvBFPVcgjkqsxzCGJKQSXZdtDTlLmnMNrR/111111112222222222222222333344555566/

# STEP 3

s/\([1-6]\)[hwHW]\1/\1/g
s/\([1-6]\)\1\1*/\1/g

# STEP 1 (part 2: remove vowels etc.)

# We don't actually remove them but "mask" them with "!"
# This avoids accidentally deleting the first character later
s/[aeiouyhwAEIOUYHW]/!/g

# Replace first character with the one saved in the hold-space

# Delete first character
s/^.//

# Append pattern-space to hold-space and swap
H
x

# Remove newline inserted by "H" above and all "!" (old vowels etc.)
s/\n//
s/!//g

# STEP 4

s/^\(....\).*$/\1/
s/^\(...\)$/\10/
s/^\(..\)$/\100/
s/^\(.\)$/\1000/

使用 soundex 值进行搜索主要取决于运气。


还:

$ paste <( printf '%s\n' * | sed -f soundex.sed ) <( printf '%s\n' * )
F236    Factorio
F230    Fasta
G500    Game
H265    HackerRank
K200    KEYS
L210    Lisp
P625    Parsing
P315    Pathfinder
P315    Pathfinder.tar.xz
Q000    QA
R165    Reformat
R123    Repositories
R564    RimWorld
S613    Scripts
U523    UNIX.dot
U521    UNIX.png
U523    UNIX.txt
W620    Work
a526    answers.txt
c313    cat-food-schedule.txt
f212    fizzbuzz
f212    fizzbuzz.c
f212    fizzbuzz2
f212    fizzbuzz2.c
p363    poetry.txt
q235    questions.txt
r200    rc
s532    soundex.sed
s532    soundex.sh
u313    utp-1.0.tar.gz

相关内容