我有一个包含许多文件的目录。而且,我忘记了确切的文件名。因此,当我想查找文件时却找不到它。
如果有任何使用 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
脚本位于当前目录中。它也不支持包含换行符的文件名。
剧本sed
(soundex.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