Bash 如何有效地拼写大量单词?

Bash 如何有效地拼写大量单词?,bash,stemming,hunspell,Bash,Stemming,Hunspell,我写了一个英文单词词干脚本,它做得很好,但当我在大文件上使用它时,它需要花费很多时间,这些文件有1000多个单词,每行一个。有没有办法加快速度?也许是完全不同的方法?不同的编程语言?不同的干扰物 file=$1 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)"

我写了一个英文单词词干脚本,它做得很好,但当我在大文件上使用它时,它需要花费很多时间,这些文件有1000多个单词,每行一个。有没有办法加快速度?也许是完全不同的方法?不同的编程语言?不同的干扰物

file=$1
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 $1}'
    else
     echo "$a" | hunspell -s -d en_US | awk 'FNR==1 {print $2}'
   fi
 else
   if [[ "$a" == *ing ]] || [[ "$a" == *ed ]]
     then
       echo "$a" | hunspell -s -d en_US | awk 'FNR==2 {print $2}'
     else
       echo "$a" | hunspell -s -d en_US | awk 'FNR==1 {print $1}'
   fi
fi
done < "$file" 
输出

cliché
womb
range
strain
fiddle
coup
earnest
touch
give
dazzle
blindfold
stagger
buy
insignia
工作原理 如果你运行hunspell-s-d en_US word,它会根据一个单词给出不同的结果。选项和要采取的行动如下:

一行一个字打印那个字 一行两个字打印第二个字 两行两个字;以ing或ed结尾,在第二行打印第二个单词 两行两个字;不以ing或ed结尾在第一行打印第一个单词
以下输出完全相同,但用于更改gived to give,这是我的拼写词典中没有的,而且速度要快得多:

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 <"$1")

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

以下输出完全相同,但用于更改give-to-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 <"$1")

请注意,这对整个文件只运行一次,而不是每个字运行一次;这是一次又一次的拼写,与bash无关,因为你的脚本一直都在bash中使用。

不要重复你自己。您可以为每个单词运行echo$a | hunspell-s-d en|u US两到三次。不要那样做。只要做一次就可以了。bash也不是在这样的大文件中运行得最快的。使用其他东西,即使只是awk,也可能快得多。如果hunspell可以在流模式下运行,您可以可靠地从中读取数据,那么您就可以做到这一点;这是您在您的条件中添加的所有子shell。如果[[$a==*ing].[$a==*ed]],您可以运行;然后:;fi实际上需要一千次执行时间来运行一个echo$a | hunspell-s-d en|u US | awk'FNR==1{print$1}。管道价格昂贵;旋转外部工具是昂贵的!还要学习使用本机bash字符串操作。此外,如果此代码有效,并且您只需要帮助使其更好,那么此问题比此站点更适合…顺便说一句,此脚本中的大多数分支打算处理的情况非常不明显。注释会很有帮助,或者至少选择测试数据来实际执行提供的所有逻辑。不要重复你自己。您可以为每个单词运行echo$a | hunspell-s-d en|u US两到三次。不要那样做。只要做一次就可以了。bash也不是在这样的大文件中运行得最快的。使用其他东西,即使只是awk,也可能快得多。如果hunspell可以在流模式下运行,您可以可靠地从中读取数据,那么您就可以做到这一点;这是您在您的条件中添加的所有子shell。如果[[$a==*ing].[$a==*ed]],您可以运行;然后:;fi实际上需要一千次执行时间来运行一个echo$a | hunspell-s-d en|u US | awk'FNR==1{print$1}。管道价格昂贵;旋转外部工具是昂贵的!还要学习使用本机bash字符串操作。此外,如果此代码有效,并且您只需要帮助使其更好,那么此问题比此站点更适合…顺便说一句,此脚本中的大多数分支打算处理的情况非常不明显。注释会很有帮助,或者至少选择测试数据来实际执行提供的所有逻辑。我如何运行它?第5行:文件:没有这样的文件或directoryfile是输入文件的名称。如果愿意,可以将其设置为$1。由于while循环在循环退出后不会设置shell所需的任何变量,因此将hunspell的输出通过管道传输到循环可能更简单,而不是重定向来自流程替换的输入。它会给出不同的结果。对不起,我的帖子最后有点误导,它是一个单列输入文件,输出也是一列。是的,这确实是误导。然后只回显$first\u root,或者更好地回显printf“%s\n”$first\u root。如何运行它?第5行:文件:没有这样的文件或directoryfile是输入文件的名称。如果愿意,可以将其设置为$1。由于while循环在循环退出后不会设置shell所需的任何变量,因此将hunspell的输出通过管道传输到循环可能更简单,而不是重定向来自流程替换的输入。它会给出不同的结果。对不起,我的帖子最后有点误导,它是一个单列输入文件,输出也是一列。是的,这确实是误导。然后只回显$first\u root,或者更好地回显printf“%s\n”$first\u root。