替换确切的单词或短语



我正在批处理文件中编写一个基于文本的冒险游戏。

长话短说,我希望程序将用户在游戏中输入的句子从第一人称转换为第二人称,只需将"I"等单数代词替换为"你"。

所以一个人说:我在盒子里搜索。 程序说:你在盒子里搜索。

为此,我使用此脚本,其中"选择"包含用户的条目。

set choice=%choice:i=you%
set choice=%choice:we=you%
set choice=%choice:us=you%
set choice=%choice:my=your%
set choice=%choice:myself=yourself%
set choice=%choice:ourselves=yourselves%
set choice=%choice:am=are% 
set choice=%choice:I'm=you're% 
set choice=%choice:I am=you are% 

但是,"I"的每个实例都会被替换。 所以当你输入:我在框内搜索。 你得到:你搜索你这个盒子。

如何告诉程序只替换确切的短语(包括空格)。 如果可能的话,我想尽量避免使用powershell。否则,我不反对想法。

像这样:

@echo off
set /p "line=Enter sentence: "
for %%f in (
"i:you"
"we:you"
"us:you"
"my:your"
"myself:yourself"
"ourselves:yourselves"
"am:are"
"I'm:you're"
) do for /F "tokens=1,* delims=:" %%g in ("%%~f") do for %%i in (%line%) do if /i "%%~g" == "%%~i" call set line=%%line:%%~i=%%~h%%
echo %line%

因此,更好的方法是包含setlocal delayedexpansion而不是call set,但是如果使用该句子,该句子可能会包含!,这些delayedexpansion将从行中删除。

如果该行在要替换的单词后包含任何特殊字符,则需要将它们添加到列表中,即i?:you?如果输入类似于Where am I,哪个会匹配?实际上将被Where are you?等取代。

第二种选择是在匹配阶段暂时替换任何特殊字符,并在完成后重新添加它们。

嗖!!您无需将I am:You are添加到列表中,因为我已经将独立IYou匹配,amare匹配。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory and filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:your files"
SET "filename1=%sourcedir%q74160637.txt"
SET "userprompt=What now"
:again
SET "response="
SET /p "response=%userprompt% ? "
IF NOT DEFINED response ECHO Goodbye&GOTO :eof
SET "reply="
FOR %%w IN (%response%) DO (
SET "subsword="
FOR /f "usebackqtokens=1*delims=:" %%o IN ("%filename1%") DO IF /i "%%o"=="%%w" SET "subsword=%%p"
IF DEFINED subsword (SET "reply=!reply! !subsword!") ELSE (SET "reply=!reply! %%w")
)
SET "reply=%reply:~1%"
ECHO %reply%
SET "userprompt=and then"
GOTO again
GOTO :EOF

请注意,如果文件名不包含空格等分隔符,则可以省略usebackq%filename1%周围的引号。

文件q74160637.txt包含的位置

i:you
we:you
us:you
my:your
myself:yourself
ourselves:yourselves
am:are
I'm:you're
I am:you are

请注意,responseset /p之前直接设置为。IEnter单独推送以响应提示,然后变量将保持不变,因此清除它意味着它将保持未定义状态。因此,在set /p后未定义的事实意味着用户刚刚按Enter退出程序。

这里的实质是%%w循环处理响应中的每个单词,因为默认分隔符是空格。然后例程从文件q74160637.txt中读取每一行,并尝试将%%w中的单词与读取行中的第一个"标记"匹配。标记是由任何字符分隔的字符串 defind 作为delims(在本例中为:);因此,行myself:yourself的第一个标记myself,行的其余部分(标记*)yourself。第一个令牌分配给%%o,第二个令牌分配给%%p(下一个按字母顺序)。请参阅提示for /?中的文档 - 或此处的数千个示例 SO。

由于subsword是在检查文件之前清除的,如果在for %%o之后定义,则找到替代单词,因此将其添加到回复字符串中,否则添加从响应中读取的单词。

串联将有一个前导空格。这可以通过set...~1..象形文字来消除。从SO这里不可避免的数千个例子的粘贴中查看set /?

请注意delayedexpansion的使用,它需要用作字符串replysubsword在(括号代码块)中被更改 - 请参阅 Stephan 的 DELAYEDEXPAND 链接或 - 你猜对了 - 这里有数千个例子。

请注意,这只会替换单词 - 替换短语会有点困难,但可以做到。

谢谢大家的回复。 我最终采用的解决方案是将输入句子中的所有空格替换为",然后执行短语匹配,然后再次用空格替换">"。

所以它最终看起来像这样

set choice=%choice: =_%
set choice=_%choice%_
set choice=%choice:_i_=_you_%
set choice=%choice:_we_=_you_%
set choice=%choice:_we_are=_you_are%
set choice=%choice:_we're_=_you're_%
set choice=%choice:_us_=_you_%
set choice=%choice:_my_=_your_%
set choice=%choice:_mine_=_yours_%
set choice=%choice:_myself_=_yourself_%
set choice=%choice:_ourselves_=_yourselves_%
set choice=%choice:_ours_=_yours_%
set choice=%choice:_our_=_your_%
set choice=%choice:_am_=_are_% 
set choice=%choice:_I'm_=_you're_% 
set choice=%choice:_I_am_=_you_are_% 
set choice=%choice:_= %

最新更新