包装 hunspell 以有效地阻止大量单词?

Wrapping hunspell to stem a large number of words efficiently?

我写了一个提取英语单词的脚本,它做得不错,但是当我在大文件上使用它时,它需要很长时间,这些文件有超过 1000 个单词,每行一个。有没有办法加快速度?也许完全不同的方法?不同的编程语言?不同的词干分析器?

file=
while read -r a
do
b="$(echo "$a" | hunspell -s -d en_US | wc -l)"
if [[ "$b" -eq 2 ]]
 then
   g="$(echo "$a" | hunspell -s -d en_US | wc -w)"
   if [[ "$g" -eq 1 ]]
    then
     echo "$a" | hunspell -s -d en_US | awk 'FNR==1 {print }'
    else
     echo "$a" | hunspell -s -d en_US | awk 'FNR==1 {print }'
   fi
 else
   if [[ "$a" == *ing ]] || [[ "$a" == *ed ]]
     then
       echo "$a" | hunspell -s -d en_US | awk 'FNR==2 {print }'
     else
       echo "$a" | hunspell -s -d en_US | awk 'FNR==1 {print }'
   fi
fi
done < "$file" 

这是它的作用的一个例子。

输入文件

cliché
womb
range
strain
fiddle
coup
earnest
touched
gave
dazzling
blindfolded
stagger
buying
insignia

输出

cliché
womb
range
strain
fiddle
coup
earnest
touch
give
dazzle
blindfold
stagger
buy
insignia

工作原理

如果你运行hunspell -s -d en_US word,它可以根据一个词给你不同的结果。选项和要采取的行动如下:

以下发出完全相同的输出(但将 gave 更改为 give,我的 hunspell 似乎在其字典中没有)——而且快得多:

last_word=; stems=( )
while read -r word stem _; do
  if [[ $word ]]; then
    last_word=$word
    [[ $stem ]] && stems+=( "$stem" )
  else
    if (( ${#stems[@]} == 0 )); then
      printf '%s\n' "$last_word"        # no stems available; print input word
    elif (( ${#stems[@]} == 1 )); then
      printf '%s\n' "${stems[0]}"       # found one stem; print it.
    else
      case $last_word in
        *ing|*ed) printf '%s\n' "${stems[1]}" ;; # "ing" or "ed": print the 2nd stem
        *)        printf '%s\n' "${stems[0]}" ;; # otherwise: print the 1st stem
      esac
    fi
    stems=( )
  fi
done < <(hunspell -s -d en_US <"")

请注意,这 hunspell 对整个文件只运行一次 ,而不是每个单词运行一次;它一遍又一遍地重新启动 hunspell,与 bash 没有任何关系,您的脚本一直在其中花费时间。