Batch file 从批处理文件中的单词列表中搜索特定单词

Batch file 从批处理文件中的单词列表中搜索特定单词,batch-file,cmd,scripting,Batch File,Cmd,Scripting,我有一个%list%变量,该变量包含单词(请参见代码),我希望搜索以字母“Y”结尾的单词(忽略区分大小写),并以用户输入的最后一个字母开头。用户输入将是任何有效的单词。找到特定单词后,我想将其存储到变量中(%myWord%)。我打算稍后在代码中使用%myWord%变量。如果我已经使用了%list%中的那个词,那么我希望向用户显示一个新词。我的单词列表以任意字母开头,以“Y”字母结尾,并按字母顺序排列。%list%相当长。 下面是我的代码。我觉得我迷路了,找不到解决这个问题的办法 @echo of

我有一个
%list%
变量,该变量包含单词(请参见代码),我希望搜索以字母“Y”结尾的单词(忽略区分大小写),并以用户输入的最后一个字母开头。用户输入将是任何有效的单词。找到特定单词后,我想将其存储到变量中(
%myWord%
)。我打算稍后在代码中使用
%myWord%
变量。如果我已经使用了
%list%
中的那个词,那么我希望向用户显示一个新词。我的单词列表以任意字母开头,以“Y”字母结尾,并按字母顺序排列。
%list%
相当长。 下面是我的代码。我觉得我迷路了,找不到解决这个问题的办法

@echo off

:START
set /p INPUTWORD=>Enter a word:
SET lastletter=%INPUTWORD:~-1%

set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
For %%L in (%list%) do (
    SET endingY=%%L:~-1%
 For %%X in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
  if findstr /i "%lastletter%" %%X EQU first letter of the words in %list%
   if %%L:~-1% EQU "y"
    if %myWord% is already shown to user then search for a new word.
     and then set myWord==%%L  (new word; unused one)

echo My Word is: %myWord%
pause
goto START
例如:

第1场会议: 输入一个单词:dog

我的话是:很高兴

第2次会议: 输入一个单词:yak

我的话是:钥匙

使用任何类型的函数都完全可以。只要它能找到合适的词。
这似乎是可能的,但我已经厌倦了思考。我想我可能需要新鲜一点。

你的描述是错误的。它说:“我想搜索一个以字母‘Y’结尾、以用户输入的第一个字母开头的单词”,但代码会查找一个以用户输入的最后一个字母开头的单词。下面我的解决方案使用代码规范

@echo off
setlocal EnableDelayedExpansion

set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"

:START
set "INPUTWORD="
set /p "INPUTWORD=>Enter a word: "
if not defined INPUTWORD goto :EOF

rem Get last letter of user's input
SET lastLetter=%INPUTWORD:~-1%

rem For each word in the list...
For %%L in (%list%) do (

   rem Store the word in "myWord" variable
   set "myWord=%%L"

   rem If the word starts with the last letter of user's input
   rem and ends with letter 'Y' (ignoring the case-sensitive)
   if /I "!myWord:~0,1!!myWord:~-1!" equ "%lastLetter%Y" (

      rem Remove the already used word from the list
      rem so the next time, a new word be shown to user
      set "list=!list:%%L=!"

      rem And break the FOR loop, because the word was found
      goto break

   )

)

rem If all words in the list was reviewed, indicate that the word was not found
set "myWord=Word not found in list"
:break

echo My Word is: %myWord%
pause
goto START
关于这个问题的几点观察:

  • 如果所有单词都以“Y”字母结尾,则无需检查此点(“单词以“Y”结尾”)
  • 单词按字母顺序排列没有任何好处。无论如何,除非开发出更复杂的方法,否则需要对整个列表进行审查,以搜索目标词

    • 您的描述是错误的。它说:“我想搜索一个以字母‘Y’结尾、以用户输入的第一个字母开头的单词”,但代码会查找一个以用户输入的最后一个字母开头的单词。下面我的解决方案使用代码规范

      @echo off
      setlocal EnableDelayedExpansion
      
      set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
      
      :START
      set "INPUTWORD="
      set /p "INPUTWORD=>Enter a word: "
      if not defined INPUTWORD goto :EOF
      
      rem Get last letter of user's input
      SET lastLetter=%INPUTWORD:~-1%
      
      rem For each word in the list...
      For %%L in (%list%) do (
      
         rem Store the word in "myWord" variable
         set "myWord=%%L"
      
         rem If the word starts with the last letter of user's input
         rem and ends with letter 'Y' (ignoring the case-sensitive)
         if /I "!myWord:~0,1!!myWord:~-1!" equ "%lastLetter%Y" (
      
            rem Remove the already used word from the list
            rem so the next time, a new word be shown to user
            set "list=!list:%%L=!"
      
            rem And break the FOR loop, because the word was found
            goto break
      
         )
      
      )
      
      rem If all words in the list was reviewed, indicate that the word was not found
      set "myWord=Word not found in list"
      :break
      
      echo My Word is: %myWord%
      pause
      goto START
      
      关于这个问题的几点观察:

      • 如果所有单词都以“Y”字母结尾,则无需检查此点(“单词以“Y”结尾”)
      • 单词按字母顺序排列没有任何好处。无论如何,除非开发出更复杂的方法,否则需要对整个列表进行审查,以搜索目标词

        • 您的描述是错误的。它说:“我想搜索一个以字母‘Y’结尾、以用户输入的第一个字母开头的单词”,但代码会查找一个以用户输入的最后一个字母开头的单词。下面我的解决方案使用代码规范

          @echo off
          setlocal EnableDelayedExpansion
          
          set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
          
          :START
          set "INPUTWORD="
          set /p "INPUTWORD=>Enter a word: "
          if not defined INPUTWORD goto :EOF
          
          rem Get last letter of user's input
          SET lastLetter=%INPUTWORD:~-1%
          
          rem For each word in the list...
          For %%L in (%list%) do (
          
             rem Store the word in "myWord" variable
             set "myWord=%%L"
          
             rem If the word starts with the last letter of user's input
             rem and ends with letter 'Y' (ignoring the case-sensitive)
             if /I "!myWord:~0,1!!myWord:~-1!" equ "%lastLetter%Y" (
          
                rem Remove the already used word from the list
                rem so the next time, a new word be shown to user
                set "list=!list:%%L=!"
          
                rem And break the FOR loop, because the word was found
                goto break
          
             )
          
          )
          
          rem If all words in the list was reviewed, indicate that the word was not found
          set "myWord=Word not found in list"
          :break
          
          echo My Word is: %myWord%
          pause
          goto START
          
          关于这个问题的几点观察:

          • 如果所有单词都以“Y”字母结尾,则无需检查此点(“单词以“Y”结尾”)
          • 单词按字母顺序排列没有任何好处。无论如何,除非开发出更复杂的方法,否则需要对整个列表进行审查,以搜索目标词

            • 您的描述是错误的。它说:“我想搜索一个以字母‘Y’结尾、以用户输入的第一个字母开头的单词”,但代码会查找一个以用户输入的最后一个字母开头的单词。下面我的解决方案使用代码规范

              @echo off
              setlocal EnableDelayedExpansion
              
              set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
              
              :START
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD goto :EOF
              
              rem Get last letter of user's input
              SET lastLetter=%INPUTWORD:~-1%
              
              rem For each word in the list...
              For %%L in (%list%) do (
              
                 rem Store the word in "myWord" variable
                 set "myWord=%%L"
              
                 rem If the word starts with the last letter of user's input
                 rem and ends with letter 'Y' (ignoring the case-sensitive)
                 if /I "!myWord:~0,1!!myWord:~-1!" equ "%lastLetter%Y" (
              
                    rem Remove the already used word from the list
                    rem so the next time, a new word be shown to user
                    set "list=!list:%%L=!"
              
                    rem And break the FOR loop, because the word was found
                    goto break
              
                 )
              
              )
              
              rem If all words in the list was reviewed, indicate that the word was not found
              set "myWord=Word not found in list"
              :break
              
              echo My Word is: %myWord%
              pause
              goto START
              
              关于这个问题的几点观察:

              • 如果所有单词都以“Y”字母结尾,则无需检查此点(“单词以“Y”结尾”)
              • 单词按字母顺序排列没有任何好处。无论如何,除非开发出更复杂的方法,否则需要对整个列表进行审查,以搜索目标词

              代码注释中包含的解释

              这看起来可能有很多代码,但实际上相当有效

              无需验证找到的单词是否以
              y
              结尾,因为您的列表只包含以
              y
              结尾的单词

              此解决方案假定列表中的所有单词至少有两个字母

              @echo off
              setlocal EnableDelayedExpansion
              
              :: The list must start and end with a space, the word order does not matter
              set "list= daddy day gladly happily key pay randomly ray say urgency utility yesterday "
              
              :start
              echo(
              
              :: Exit if list is empty (nothing but spaces)
              if "%list: =%" equ "" (
                echo No more words in list
                exit /b
              )
              
              :: Get the users input, exit if none
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD exit /b
              
              :: Look for the first word that begins with the last letter of the input
              :: and delete everything up through the first letter of the matching word
              set "test=!list:* %INPUTWORD:~-1%=!"
              
              :: If the modified list matches the original, then no word was found.
              :: Give message and try again
              if "%test%" equ "%list%" (
                echo myWord not found
                goto :start
              )
              
              :: Get the remainder of the word and rebuild the complete word
              for %%W in (%test%) do (
                set "myWord=%INPUTWORD:~-1%%%W"
                goto :break
              )
              :break
              
              :: Remove the word from the list
              set "list=!list: %myWord% = !"
              
              :: Show the result and loop back
              echo myWord=%myWord%
              goto :start
              

              代码注释中包含的解释

              这看起来可能有很多代码,但实际上相当有效

              无需验证找到的单词是否以
              y
              结尾,因为您的列表只包含以
              y
              结尾的单词

              此解决方案假定列表中的所有单词至少有两个字母

              @echo off
              setlocal EnableDelayedExpansion
              
              :: The list must start and end with a space, the word order does not matter
              set "list= daddy day gladly happily key pay randomly ray say urgency utility yesterday "
              
              :start
              echo(
              
              :: Exit if list is empty (nothing but spaces)
              if "%list: =%" equ "" (
                echo No more words in list
                exit /b
              )
              
              :: Get the users input, exit if none
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD exit /b
              
              :: Look for the first word that begins with the last letter of the input
              :: and delete everything up through the first letter of the matching word
              set "test=!list:* %INPUTWORD:~-1%=!"
              
              :: If the modified list matches the original, then no word was found.
              :: Give message and try again
              if "%test%" equ "%list%" (
                echo myWord not found
                goto :start
              )
              
              :: Get the remainder of the word and rebuild the complete word
              for %%W in (%test%) do (
                set "myWord=%INPUTWORD:~-1%%%W"
                goto :break
              )
              :break
              
              :: Remove the word from the list
              set "list=!list: %myWord% = !"
              
              :: Show the result and loop back
              echo myWord=%myWord%
              goto :start
              

              代码注释中包含的解释

              这看起来可能有很多代码,但实际上相当有效

              无需验证找到的单词是否以
              y
              结尾,因为您的列表只包含以
              y
              结尾的单词

              此解决方案假定列表中的所有单词至少有两个字母

              @echo off
              setlocal EnableDelayedExpansion
              
              :: The list must start and end with a space, the word order does not matter
              set "list= daddy day gladly happily key pay randomly ray say urgency utility yesterday "
              
              :start
              echo(
              
              :: Exit if list is empty (nothing but spaces)
              if "%list: =%" equ "" (
                echo No more words in list
                exit /b
              )
              
              :: Get the users input, exit if none
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD exit /b
              
              :: Look for the first word that begins with the last letter of the input
              :: and delete everything up through the first letter of the matching word
              set "test=!list:* %INPUTWORD:~-1%=!"
              
              :: If the modified list matches the original, then no word was found.
              :: Give message and try again
              if "%test%" equ "%list%" (
                echo myWord not found
                goto :start
              )
              
              :: Get the remainder of the word and rebuild the complete word
              for %%W in (%test%) do (
                set "myWord=%INPUTWORD:~-1%%%W"
                goto :break
              )
              :break
              
              :: Remove the word from the list
              set "list=!list: %myWord% = !"
              
              :: Show the result and loop back
              echo myWord=%myWord%
              goto :start
              

              代码注释中包含的解释

              这看起来可能有很多代码,但实际上相当有效

              无需验证找到的单词是否以
              y
              结尾,因为您的列表只包含以
              y
              结尾的单词

              此解决方案假定列表中的所有单词至少有两个字母

              @echo off
              setlocal EnableDelayedExpansion
              
              :: The list must start and end with a space, the word order does not matter
              set "list= daddy day gladly happily key pay randomly ray say urgency utility yesterday "
              
              :start
              echo(
              
              :: Exit if list is empty (nothing but spaces)
              if "%list: =%" equ "" (
                echo No more words in list
                exit /b
              )
              
              :: Get the users input, exit if none
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD exit /b
              
              :: Look for the first word that begins with the last letter of the input
              :: and delete everything up through the first letter of the matching word
              set "test=!list:* %INPUTWORD:~-1%=!"
              
              :: If the modified list matches the original, then no word was found.
              :: Give message and try again
              if "%test%" equ "%list%" (
                echo myWord not found
                goto :start
              )
              
              :: Get the remainder of the word and rebuild the complete word
              for %%W in (%test%) do (
                set "myWord=%INPUTWORD:~-1%%%W"
                goto :break
              )
              :break
              
              :: Remove the word from the list
              set "list=!list: %myWord% = !"
              
              :: Show the result and loop back
              echo myWord=%myWord%
              goto :start
              

              这种解决方案应该是最有效的方法,因为它根据单词的第一个字母将原始列表拆分为子列表。这样,通过
              if defined子列表[%lastLetter%]
              立即测试某个单词是否存在,并在更短的变量中提取该单词。此外,由于代码的大小,此方法是明确的

              @echo off
              setlocal EnableDelayedExpansion
              
              set "list=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
              
              rem Split the list in sub-lists (an array) based on the first letter of the words
              for %%w in (%list%) do (
                 set "word=%%w"
                 for /F %%l in ("!word:~0,1!") do set "subList[%%l]=!subList[%%l]! %%w"
              )
              
              ECHO CONTENTS OF THE SUB-LISTS:
              SET SUBLIST
              ECHO/
              
              :START
              set "INPUTWORD="
              set /p "INPUTWORD=>Enter a word: "
              if not defined INPUTWORD goto :EOF
              
              rem Get last letter of user's input
              SET lastLetter=%INPUTWORD:~-1%
              
              rem If a sub-list for that letter exists...
              if defined subList[%lastLetter%] (
              
                 rem Extract the first word from such sub-list
                 for /F "tokens=1*" %%a in ("!subList[%lastLetter%]!") do (
                    set "myWord=%%a"
                    set "subList[%lastLetter%]=%%b"
                 )
              
              ) else (
                 set "myWord=Word not found in list"
              )
              
              echo My Word is: %myWord%
              echo/
              goto START
              
              示例会话:

              CONTENTS OF THE SUB-LISTS:
              subList[d]= daddy day
              subList[g]= gladly
              subList[h]= happily
              subList[k]= key
              subList[p]= pay
              subList[r]= randomly ray
              subList[s]= say
              subList[u]= urgency utility
              subList[y]= yesterday
              
              >Enter a word: dog
              My Word is: gladly
              
              >Enter a word: yak
              My Word is: key
              
              >Enter a word: dad
              My Word is: daddy
              
              >Enter a word: dad
              My Word is: day
              
              >Enter a word: dad
              My Word is: Word not found in list
              
              >Enter a word:
              
              有关批处理中阵列的进一步说明,请参阅

              编辑:我试图在我的解决方案与dbenham的解决方案之间实施一个计时测试,但我无法完成它

              @echo off
              setlocal EnableDelayedExpansion
              
              set "list0=daddy day gladly happily key pay randomly ray say urgency utility yesterday"
              
              rem Create the initial list repeating the previous "list0" 100 times (= 1200 words)
              rem changing the initial letter by a random one
              
              echo Creating initial list...
              set "letter=abcdefghijklmnopqrstuvwxyz"
              set "list="
              for /L %%t in (1,1,100) do (
                 for %%a in (%list0%) do (
                    set "word=%%a"
                    set /A i=!random! %% 26
                    for /F %%i in ("!i!") do set "list=!list! !letter:~%%i,1!!word:~1!"
                 )
              )
              
              
              rem ========================
              echo Testing Aacini's
              
              rem Start Aacini's code test
              for /F "tokens=1-3 delims=:." %%a in ("%time%") do (
                 set /A "H=%%a, M=1%%b%%100, S=1%%c%%100, startA=(H*60+M)*60+S"
              )
              
              rem Split the list in sub-lists (an array) based on the first letter of the words
              for %%w in (%list%) do (
                 set "word=%%w"
                 for /F %%l in ("!word:~0,1!") do set "subList[%%l]=!subList[%%l]! %%w"
              )
              
              rem Get 1000 words selecting a random last letter 
              
              for /L %%? in (1,1,1000) do (
              
              set /A i=!random! %% 26
              for /F %%i in ("!i!") do SET "lastLetter=!letter:~%%i,1!"
              
              rem If a sub-list for that letter exists...
              if defined subList[!lastLetter!] (
              
                 rem Extract the first word from such sub-list
                 for /F %%L in ("!lastLetter!") do for /F "tokens=1*" %%a in ("!subList[%%L]!") do (
                    set "myWord=%%a"
                    set "subList[%%L]=%%b"
                 )
              
              ) else (
                 set "myWord=Word not found in list"
              )
              
              echo %%?- My Word is: !myWord!
              REM echo/
              REM goto START
              )
              
              rem End Aacini's code test
              for /F "tokens=1-3 delims=:." %%a in ("%time%") do (
                 set /A "H=%%a, M=1%%b%%100, S=1%%c%%100, endA=(H*60+M)*60+S"
              )
              
              
              rem ========================
              echo Testing dbenham's
              
              
              rem Start dbenham's code test
              
              :: The list must start with dot space and end with space dot, the word order does not matter
              set "list=. %list% ."
              
              for /F "tokens=1-3 delims=:." %%a in ("%time%") do (
                 set /A "H=%%a, M=1%%b%%100, S=1%%c%%100, startD=(H*60+M)*60+S"
              )
              
              rem Get 1000 words selecting a random last letter 
              
              for /L %%? in (1,1,1000) do (
              
              set /A i=!random! %% 26
              for /F %%i in ("!i!") do SET "LastLetter=!letter:~%%i,1!"
              
              REM :start
              REM echo(
              
              Rem Exit if list is empty
              if "!list: =!" equ ".." (
                echo No more words in list
                goto endDbenham
              )
              
              Rem Iterate value of list after replacing "<space>%LastLetter%" with "<newLine>%LastLetter%".
              Rem Skip the first line and take the first token, which will be myWord.
              Rem If no substitution, then only one line so DO will not fire.
              Rem The empty line below (after the FOR line^) is critical - DO NO REMOVE
              set "break="
              for /F %%L in ("!LastLetter!") do for /f "usebackq skip=1" %%W in ('!list: %%L^=^
              
              %%L!') do if not defined break (                    
              
                REM remove myWord from the list
                set "list=!list: %%W = !"
              
                REM show result and loop back for more (breaks out of loop^)
                echo %%?- myWord = %%W
                REM goto :start
                set "break=Yes"
              )
              
              if not defined break (
              Rem Only reaches here if myWord not found
              echo %%?- myWord not found
              REM goto :start
              )
              
              )
              
              
              rem =======================
              
              :endDbenham
              
              rem End dbenham's code test
              for /F "tokens=1-3 delims=:." %%a in ("%time%") do (
                 set /A "H=%%a, M=1%%b%%100, S=1%%c%%100, endD=(H*60+M)*60+S"
              )
              
              set /A elapsedA=endA-startA, elapsedD=endD-startD
              echo/
              echo Aacini's:  %elapsedA% seconds
              echo dbenham's: %elapsedD% seconds
              
              @echo关闭
              setlocal EnableDelayedExpansion
              设置“list0=爸爸节快乐快乐键随机支付ray昨天说的紧急实用程序”
              rem创建初始列表,重复上一个“list0”100次(=1200字)
              rem将首字母更改为随机字母
              回声创建初始值