我创建了文本文件Test.txt,内容如下:
Hello world my name is John Doe, but you knew that video5c
Hello world my name is Jane Doe video3v: but you knew that
Hello world my name is Superman: but you knew that 1f
Hello world my name is Asterix, Gallier 43: but you knew that 1f
34: but you knew that this is an invalid title
, but you knew that this is also an invalid title
but you knew that this is an invalid title, too
然后我开发了以下注释批处理文件来评估所有标题行:
@echo off
setlocal EnableDelayedExpansion
set "FileTitle="
for /F "usebackq delims=" %%L in ("Test.txt") do (
call :GetTitle "%%L"
echo Get from "%%L"
echo the title "!FileTitle!"
echo.
)
endlocal
goto :EOF
:GetTitle
set "Line=%~1"
rem Replace the string " but you knew that" case insensitive
rem by character # with a comma before which is always removed.
set "Line=%Line: but you knew that=,#%"
rem Use character # as separator to get everything left of this character.
for /F "tokens=1 delims=#" %%T in ("%Line%") do set "FileTitle=%%T"
if "%FileTitle%" == "," goto TitleError
set "FileTitle=%FileTitle:~0,-1%"
:RemoveSpaces
if "%FileTitle%" == "" goto TitleError
if "%FileTitle:~-1%" == " " set "FileTitle=%FileTitle:~0,-1%" & goto RemoveSpaces
rem Is the last character a comma, remove this character, too.
if "%FileTitle:~-1%" == "," (
set "FileTitle=%FileTitle:~0,-1%"
if "!FileTitle!" == "" goto TitleError
goto RemoveSpaces
)
rem Is the last character not a colon, we have the file title.
if not "%FileTitle:~-1%" == ":" goto :EOF
rem Otherwise remove the colon and the word left to the
rem colon if this word contains also at least 1 digit.
set "FileTitle=%FileTitle:~0,-1%"
set "LastWord="
rem The first condition in code below should be never true according to
rem provided sample data, but it is necessary to avoid an endless loop.
:RemoveWord
if "%FileTitle%" == "" goto TitleError
if "%FileTitle:~-1%" == " " goto EvaluateWord
set "LastWord=%FileTitle:~-1%%LastWord%"
set "FileTitle=%FileTitle:~0,-1%"
goto RemoveWord
:EvaluateWord
for /L %%C in (0,1,9) do (
if not "!LastWord:%%C=!" == "%LastWord%" goto RemoveSpaces
)
rem Append the removed word as it does not contain a digit.
rem Then we have the file title and can exit the subroutine.
set "FileTitle=%FileTitle%%LastWord%"
goto :EOF
:TitleError
set "FileTitle=Error: No file title found^!"
goto :EOF
在命令提示符窗口中执行的这个批处理文件输出:
Get from "Hello world my name is John Doe, but you knew that video5c"
the title "Hello world my name is John Doe"
Get from "Hello world my name is Jane Doe video3v: but you knew that"
the title "Hello world my name is Jane Doe"
Get from "Hello world my name is Superman: but you knew that 1f"
the title "Hello world my name is Superman"
Get from "Hello world my name is Asterix, Gallier 43: but you knew that 1f"
the title "Hello world my name is Asterix, Gallier"
Get from "34: but you knew that this is an invalid title"
the title "Error: No file title found!"
Get from ", but you knew that this is also an invalid title"
the title "Error: No file title found!"
Get from " but you knew that this is an invalid title, too"
the title "Error: No file title found!"
此批处理文件中的函数GetTitle 使用命令FOR 和SET 大量字符串替换来确定每个标题。
如果输出符合您对这些行的期望,请使用函数 GetTitle。
要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
setlocal /?
我的下一个版本使用更新的示例数据:
Hello world my name is awesome
Hello world my name is awesome, but you knew that video c5
Hello world my name is awesome video3 v: Everybody knows I am r
Hello world my name is awesome: It got 100 likes in 10 min 1f
Hello world my name is awesome 43 video 2: Did you know that:
Hello world my name is awesome a3: It is Mr smokealot 1f,
使用首次定义的规则,批处理代码现在比以前容易得多:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FileTitle="
for /F "usebackq delims=" %%L in ("Test.txt") do (
call :GetTitle "%%L"
echo Get from "%%L"
echo the title "!FileTitle!"
echo.
)
endlocal
goto :EOF
:GetTitle
rem Get string left from first comma or first colon. The entire line
rem is returned if the line does not contain any comma or colon.
for /F "tokens=1 delims=,:" %%T in ("%~1") do set "WordsList=%%T"
rem Process each word from list and check for containing any digit, or being
rem a single letter different than upper case "I", or being the word "video".
rem Those words are ignored on building the file title from the words list.
rem It is expected here that non of the words contain a non word character
rem as this could result in a syntax error on processing the words.
set "FileTitle="
for %%I in (%WordsList%) do (
set "Skip=0"
for /F "tokens=1 delims=0123456789" %%W in ("#%%I#") do set "Word=%%W"
if "!Word!" NEQ "#%%I#" set "Skip=1"
set "Word=%%I"
if "!Word:~0,1!" EQU "%%I" (
if "%%I" NEQ "I" set "Skip=1"
)
if /I "%%I" EQU "video" set "Skip=1"
if "!Skip!" EQU "0" set "FileTitle=!FileTitle! %%I"
)
rem Was there not at least 1 valid word found?
if "%FileTitle%" == "" set "FileTitle= Error: No file title found."
rem Remove the leading space and exit subroutine GetTitle.
set "FileTitle=%FileTitle:~1%"
goto :EOF
示例输入数据的输出为:
Get from "Hello world my name is awesome"
the title "Hello world my name is awesome"
Get from "Hello world my name is awesome, but you knew that video c5"
the title "Hello world my name is awesome"
Get from "Hello world my name is awesome video3 v: Everybody knows I am r"
the title "Hello world my name is awesome"
Get from "Hello world my name is awesome: It got 100 likes in 10 min 1f"
the title "Hello world my name is awesome"
Get from "Hello world my name is awesome 43 video 2: Did you know that:"
the title "Hello world my name is awesome"
Get from "Hello world my name is awesome a3: It is Mr smokealot 1f,"
the title "Hello world my name is awesome"
还有一个和Stephan非常相似的版本:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FileTitle="
for /F "usebackq delims=" %%L in ("Test.txt") do (
call :GetTitle "%%L"
echo !FileTitle!
)
endlocal
goto :EOF
:GetTitle
rem Get string left from first comma or first colon. The entire line
rem is returned if the line does not contain any comma or colon.
for /F "tokens=1 delims=,:" %%T in ("%~1") do set "WordsList=%%T"
rem Process each word from list and check for containing any digit, or being
rem a single letter different than upper case "I", or being the word "video".
rem Those words are ignored and all other remaining words on building the
rem file title from the words list. It is expected here that non of the words
rem contain a non word character as this could result in a syntax error on
rem processing the words.
set "FileTitle="
for %%I in (%WordsList%) do (
for /F "tokens=1 delims=0123456789" %%W in ("#%%I#") do set "Word=%%W"
if "!Word!" NEQ "#%%I#" goto CheckTitle
set "Word=%%I"
if "!Word:~0,1!" EQU "%%I" (
if "%%I" NEQ "I" goto CheckTitle
)
if /I "%%I" EQU "video" goto CheckTitle
set "FileTitle=!FileTitle! %%I"
)
:CheckTitle
rem Was there not at least 1 valid word found?
if "%FileTitle%" == "" set "FileTitle= Error: No file title found."
rem Remove the leading space and exit subroutine GetTitle.
set "FileTitle=%FileTitle:~1%"
goto :EOF
Stephan´s answer 中发布的示例输入数据的输出是:
Hello world my name is awesome
Hello world my name is awesome
Hello world my name is awesome
Hello world my name is awesome
Hello world my name is awesome
Hello world my name is John Doe
Hello world my name is Jane Doe
Hello world my name is Superman
Hello world my name is Asterix
Error: No file title found.
Any string is
Any word that contains
Stephan 的代码产生的输出的不同之处在于,不是I 的单个字符单词会导致退出单词处理循环并因此截断该单词的标题。
可以通过删除代码行来改变这种单字符单词的行为:
set "Word=%%I"
if "!Word:~0,1!" EQU "%%I" (
if "%%I" NEQ "I" goto CheckTitle
)
那么第三个批处理代码的输出将与Stephan 编写的批处理代码产生的输出相同,除了错误消息而不是空行。
PS:这是一个很好的例子,如果提问者没有通过发布有问题的预期输出数据来明确提供的输入数据的输出数据应该是什么。