如何找到遵循特定順序的單字

如何找到遵循特定順序的單字

我正在嘗試編寫一個腳本(script1.sh),當給定一堆字母時,腳本可以找到每個可能的單字。

  • 這些單字必須以混亂的第一個字母開始,以最後一個字母結束。

  • 單字的字母需要遵循混亂中字母的順序。

  • 混亂中的每個字母都可以多次使用。

所以這

./script1.sh "qwertyuytresdftyuiokn"

應該輸出queenquestion不是“quieten”,因為“e”在混亂中出現在“u”和“i”之前。

我嘗試將第一個、最後一個和剩餘的字母分配給變量,然後使用egrep查找單詞,但我找不到使用字母順序的方法。所以這個也給了我無效的字。

#!/bin/bash

first_letter=$(echo $@ | cut -c1)
last_letter=$(echo $@ |rev| cut -c1)
remaining_letters=$(echo $@ | cut -c2- | rev | cut -c2-)

grep -E "^$first_letter[$remaining_letters]*$last_letter$" /usr/share/dict/words

然後我嘗試將混亂變成數組,但我再次找不到一種方法來找到遵循混亂中順序的單字。

答案1

#!/bin/sh
pttrn="^$(printf '%s' "$1" | sed -e 's/\(.\)/\1*/g' -e 's/\*/\\+/' -e 's/\*$/\\+/')"'$'
grep "$pttrn" /usr/share/dict/words

透過在每個字元之後注入,從第一個參數獲得模式*。然後第一個*改為\+;最後也是如此*。另外^$添加了 和 。您的範例輸入產生以下模式:

^q\+w*e*r*t*y*u*y*t*r*e*s*d*f*t*y*u*i*o*k*n\+$

此模式是正確的模式grepq開頭必須至少出現一次,n結尾必須至少出現一次。中間的每個字母可能出現零次或多次,順序保持不變。

請注意,該腳本很愚蠢。如果您提供帶有.[]等輸入,那麼您將得到超出規範的正規表示式。提供合理的輸入或擴展腳本以驗證它。


例子:

$ ./script1.sh qwertyuytresdftyuiokn
queen
question
$ ./script1.sh te
tee
$ ./script1.sh superuser
seer
serer
spur
super
supper
surer
$

答案2

這是一種解決方法

首先,過濾單字列表,僅保留那些以與混雜字母相同的字母開頭和結尾的單字。例如,如果混亂作為位置參數傳遞$1(並假設最近的bashshell)

grep -x "${1:0:1}.*${1:(-1):1}" /usr/share/dict/words

然後將這些單字中的每一個都分解成一個正規表示式 - 我想不出一個「好的」方法來做到這一點,但是使用 GNU sed 你可以這樣做

$ sed -E 's/(.)\1*/+.*\1/2g' <<< "queen"
q+.*u+.*e+.*n

現在針對每個產生的模式測試混亂情況。

把它們放在一起:

$ cat script1 
#!/bin/bash

wordlist=/usr/share/dict/words

while IFS= read -r word; do 
  grep -qEx "$(sed -E 's/(.)\1*/+.*\1/2g' <<< "$word")" <<< "$1" && printf '%s\n' "$word"
done < <(grep -x "${1:0:1}.*${1:(-1):1}" "$wordlist")

然後

$ ./script1 qwertyuytresdftyuiokn
queen
question

答案3

這是另一個(在 中運行bashpython程式碼產生正規表示式並將其提供給grepgrep然後處理古老look實用程式的輸出,該實用程式執行二分搜尋以拉回範例中/usr/share/dict/words以 開頭的所有單字。因此要搜尋的單字集大大減少qgrep

python3 -c 'import sys
arr = list(sys.argv[1])
print(*arr, sep="*")
' $1 | grep -x -f - <(look ${1:0:1})

或者,避免使用正規表示式的look+解決方案python3

look q | ./finder.py "qwertyuytresdftyuiokn"

其中finder.py如下:

#!/usr/bin/env python3
import sys
from itertools import groupby

seek_word = sys.argv[1]
for word in sys.stdin:
    orig_word = word.strip()
    word = ''.join(k for k, g in groupby(orig_word)) 
    s_w = iter(seek_word)
    i_word = iter(word)
    if all(c in s_w for c in i_word) and not next(s_w, None):
        print(orig_word)

相關內容