string - 如何使用 FINDSTR 查找变量值中的字符串?

标签 string batch-file cmd

是否可以将FINDSTR与变量而不是文件一起使用?

我已经尝试对此进行研究,但我对批处理的了解还不够。

我已经使我的大部分批处理文件完美地满足了我的需要,但是我在将字符串变量的一部分提取到新变量中时遇到了问题。

例如,原始变量为S02E12 - Charge!。我想将 02 提取到 ep_seas,将 12 提取到 ep_num,然后将 Charge! 提取出来> 到 ep_name。如果这是确切的名称模式,我现在可以正常工作,但我遇到了一些采用这种模式的文件:S02E124 - Charge #2!

有没有办法可以动态获取我需要的值,而不管它们的长度如何?

我的想法是使用 FINDSTRSE 之间搜索,然后在 E 和空格  (或 -),然后在 - 和末尾之间。但我不确定如何继续。

有人有我可以研究的解决方案或者有人可以提供示例吗?

setlocal DisableDelayedExpansion
set mkvmerge="C:/Program Files/MKVToolNix/mkvmerge.exe"
set "output_folder=%cd%\Muxing"
for /r %%a in (*.mkv) do (
    set fi=%%a
    set ep=%%~na
    call :merge
)
goto :eof

:merge
set ep_name=%ep:~9%
set ep_num=%ep:~4,2%
set ep_seas=%ep:~2,1%
call %mkvmerge% -o "%output_folder%\%ep%.mkv" --track-name "0:%ep_name%" --language 0:und --default-track 0:yes --track-name "1:[JAP]" --language 1:jpn --default-track 1:yes --track-name "2:[ENG]" --language 2:eng --default-track 2:yes --forced-track 2:yes "%fi%" --track-order 0:0,0:1,0:2 --title "Fate Zero - Episode %ep_num%"
goto :eof

最佳答案

您可以使用此代码来完成您的任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "output_folder=%CD%\Muxing"
for /R %%I in (*.mkv) do (
    set "fi=%%I"
    set "ep=%%~nI"
    call :merge
)
goto :EOF

:merge
for /F "tokens=1,2* delims=ES- " %%A in ("%ep%") do (
    set "ep_seas=%%A"
    set "ep_num=%%B"
    set "ep_name=%%C"
)
"%ProgramFiles%\MKVToolNix\mkvmerge.exe" -o "%output_folder%\%ep%.mkv" --track-name "0:%ep_name%" --language 0:und --default-track 0:yes --track-name "1:[JAP]" --language 1:jpn --default-track 1:yes --track-name "2:[ENG]" --language 2:eng --default-track 2:yes --forced-track 2:yes "%fi%" --track-order 0:0,0:1,0:2 --title "Fate Zero - Episode %ep_num%"
goto :EOF

这里使用的命令FOR/F解析双引号中的字符串,即文件名。

选项 "tokens=1,2* delims=ES- " 会导致使用 4 个指定字符作为分隔符将文件名字符串 S02E12 - Charge!S02E124 - Charge #2! 拆分为 3 个子字符串。

  1. token 1 是分配给指定循环变量 02 的两个文件名的 A
  2. token 2 是 12124,根据 ASCII 表(即 A)分配给 B 之后的下一个循环变量的两个文件名。
  3. token 3 是 token 2 之后的分隔符之后的所有内容,即分配给下一个循环变量 Charge! 的两个文件的 Charge #2!C

您现在知道为什么循环变量区分大小写而环境变量不区分大小写了。指定的循环变量定义下一个循环变量在使用带有多个标记/子字符串的 for /F 时具有哪些字符。

* 附加到标记数字 X 表示子字符串 X 之后的分隔符后的字符串/行的其余部分应分配给下一个循环变量,而不需要进一步拆分分隔符。因此,S02E12 - S02E124 -  之后的字符串也可以包含分隔符,但仍会完全分配给循环变量 C

请注意,连字符和空格后以 E 或 S 开头的字符串也被解释为分隔符,因此在分配给循环变量 C 的字符串中缺失。子例程 merge 中的 FOR 循环可以替换为以下代码,以获得像 S03E48 - Extended Version.mkv 这样的文件名的工作解决方案。

for /F "tokens=1* delims=- " %%A in ("%ep%") do (
    set "ep_name=%%B"
    for /F "tokens=1,2 delims=ES" %%C in ("%%A") do (
        set "ep_seas=%%C"
        set "ep_num=%%D"
    )
)

外循环将 S03E48 分配给循环变量 A 并将 Extended Version 分配给循环变量 B 。内部循环再次将 S03E48 拆分为分配给循环变量 03C 和分配给循环变量 48D

顺便说一句:Windows 上的目录分隔符是 \,而不是 Unix/Linux/Mac 上的 /,尽管 Windows 内核函数还支持使用 / 的文件/目录路径,并自动更正为 \

为了了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • set /?
  • setlocal /?

最后一点:

可以在环境变量上使用FINDSTR,例如:

echo %ep% | findstr /R "^S[0123456789][0123456789]"

但是FINDSTR永远不会只输出匹配的字符串。它始终输出包含找到的字符串的整行。因此,FINDSTR 对于将文件名分割成单独的部分没有任何帮助。

关于string - 如何使用 FINDSTR 查找变量值中的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46553570/

相关文章:

windows - 如何使用批处理语言的timeout命令?

Java:使用 exec() 方法在其他文本文件中重定向 .bat 文件的输出?

c - strcasecmp() : A Non-Standard Function?

string - 为什么将无符号整数转换为字节数组形式的前缀为 "3"的字符串?

powershell - 尝试从 .bat 文件启动 powershell 脚本并获取返回值

batch-file - 在批处理脚本中旋转亲和性值以进行循环

.net - F# 环境集成(用于脚本)

windows - 如何在 MS Windows 中更改 "local system"帐户的 %PATH% 值?

c# - 字符串内部的字符串 Ex : pie = "He said "hi""- C#

java - 在多维数组中设置字符串