ファイル検索で Soundex 検索を使用するにはどうすればいいですか?

ファイル検索で Soundex 検索を使用するにはどうすればいいですか?

多数のファイルを含むディレクトリがあります。しかも、正確なファイル名を忘れてしまいました。そのため、ファイルを探そうとしても見つかりません。

検索に Soundex アルゴリズムを使用するツールがあれば、私のケースに役立ちます。

答え1

これは私自身の好奇心から書いた回答です。おそらく、「主に発音に基づいて類似の文字列を検索する Unix コマンドはありますか?Text::Soundexこれを使用する代わりに、「(Perlモジュール)」を使用します。


次のシェル スクリプトと付随する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

シェルスクリプト(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" {} +

スクリプトは、sedスクリプト (以下) を使用して検索語の soundex 値を計算します。次に、 を使用しfindて現在のディレクトリまたはそれ以下のすべての名前を検索し、検索語と同じ方法でそれぞれに対して soundex 値を計算します。ファイル名の soundex 値が検索語の soundex 値と一致する場合、そのファイルへの完全なパスが出力されます。

シェル スクリプトが少し基本的なものであることは認めます。たとえば、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」を実装しますWikipediaで説明されているように最初の文字は変更されません (アルファベットでない場合は削除する)。そのため、trシェル スクリプト内で文字列を大文字にします。

これは徹底的にテストされたわけではありませんが、Wikipedia の記事に記載されている名前を正しく処理しているようです。

注釈付きバージョン (「手順」は、上記の Wikipedia の記事の手順を指します):

# 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

関連情報