【问题标题】:Batch file: evaluating command output with regex?批处理文件:使用正则表达式评估命令输出?
【发布时间】:2018-05-27 18:36:21
【问题描述】:

我根据在别处找到的一些示例制作了一个 Windows 批处理文件。 它的作用是解析特定文件类型 (.mkv) 的文件夹,然后从 MKVToolNix 文件夹运行 mkvmerge.exe。 该命令产生一个输出,列出容器中的不同轨道。

文件的核心是

 set rootfolder="Z:\Movies"
 for /r %rootfolder% %%a in (*.mkv) do (
   for /f %%b in ('mkvmerge -i "%%a" ^| find /c /i "chapters"') do (
     if [%%b]==[0] (
       echo "%%a" has no chapters
     ) else (
       echo Doing some interesting stuff!
     )
   )
 )

上面的例子只是文件的一部分,rootfolder 设置为我要解析的文件夹,当然,当找到一个包含章节的文件时,它会运行额外的命令。 这一切都很好,但我也想同时检查字幕。 find 命令不使用正则表达式,或者我可以添加“章节字幕”。我使用其他命令(如 findstr)的努力并没有真正奏效。 如何在此处使用 RegEx?

这是一个示例输出,在 .mkv 文件上运行 mkvmerge.exe

mkvmerge.exe -i "Snow White and the Seven Dwarfs (1937) [tt0029583].mkv"
File 'Snow White and the Seven Dwarfs (1937) [tt0029583].mkv': container: Matroska
Track ID 0: video (MPEG-4p10/AVC/h.264)
Track ID 1: audio (DTS)
Track ID 2: audio (AC-3)
Track ID 3: subtitles (HDMV PGS)
Track ID 4: subtitles (HDMV PGS)
Chapters: 26 entries

这个例子有字幕和章节轨道,批处理文件会找到关键字“章节”(它被设置为忽略大小写)。即使没有章节,我也想捕获包含关键字“字幕”的文件。

为了澄清我的意图,我希望代码:

  • 通过给定文件夹解析
  • 对于所有 .mkv 文件,执行 mkvmerge /i 这将输出(作为文本)该文件中的流
  • 查看该输出,如果它包含单词“章节”和/或“字幕”,则会触发一些操作。

【问题讨论】:

  • 您应该提供要解析的示例输出。不是每个人都使用 mkvmerge。
  • 谢谢,我将添加一个示例输出,尽管在撰写本文时我认为没有必要。这里的重点是扫描 2 个关键字中的任何一个,而不仅仅是一个。
  • 您还应该分享您的(失败的)findstr 尝试...
  • 好点 aschipfl,但由于我不了解 for /f 循环的机制或输出格式,它们除了空变量或不正确的语法外从来没有任何意义。

标签: regex batch-file find


【解决方案1】:

由于您似乎没有区分是否检测到一个字符串或另一个(或两者),那么

@Echo off
set rootfolder="Z:\Movies"
for /r %rootfolder% %%a in (*.mkv) do (
 mkvmerge -i "%%a" | findstr /i "^Chapters subtitles" >nul
 if errorlevel 1 (
  echo Neither Chapters nor subs found in "%%a"
 ) else (
  echo Chapters or subs found in "%%a"
 )
)

可能会更容易。

【讨论】:

  • 看准了!这正是我想要达到的目标。我花了一段时间才发现缺少的 ( 在 if 语句中。
  • @KarstenJensen 如果此答案解决了您的问题,请通过选择答案左侧的灰色勾号将其选为正确答案。
【解决方案2】:

感谢 LotPings 的努力。我学到了一些关于代币的东西,这将非常有用。你的脚本也让我走上了正轨(在途中学习了更多命令。

你的脚本最终看起来像这样:

:: Q:\Test\2018\05\27\SO_50555308.cmd
@Echo off
set rootfolder="Z:\Movies"
for /r %rootfolder% %%a in (*.mkv) do (
    set "found="
    for /f "tokens=1-4* delims=: " %%b in (
        'mkvmerge -i "%%a" ^| findstr /i "^Chapters subtitles"'
    ) do (
        if /i "%%b"=="Chapters" set found=1
        if /i "%%e"=="subtitles" set found=1
    )
    if defined found (
        echo Chapters or subs found in "%%a"
    ) else (
        echo.
    )
)

我只需要检查我的一个关键字是否存在于任何标记中,然后相应地设置一个标志,然后在循环执行适当的操作后,为下一个文件重置标志。

【讨论】:

    【解决方案3】:

    仍然不清楚Subtitles 的行会是什么样子。
    假设值 ChaptersSubtitles 出现在第一列
    for /f 将冒号和空格处的行(相邻的分隔符算作一个)拆分为标记 1=%%b 和 2=%%c 标记 3=%%d 中可能未拆分的其余部分 在行开头锚定^ 的空格分隔(ORed)正则表达式搜索词将仅匹配章节/字幕。

    :: Q:\Test\2018\05\27\SO_50555308.cmd
    @Echo off
    set rootfolder="Z:\Movies"
    for /r %rootfolder% %%a in (*.mkv) do (
        for /f "tokens=1-4* delims=: " %%b in (
            'mkvmerge -i "%%a" ^| findstr /i "^Chapters subtitles"'
        ) do (
            if /i "%%b"=="Chapters" if "%%c"=="0" (
                echo "%%a" has no chapters
            ) else (
                echo "%%a" has %%c chapters
                echo Doing some interesting stuff!
            )
            if /i "%%e"=="subtitles" echo "%%a" %%b %%b %%d: %%e %%f
        )
    )
    

    【讨论】:

    • 谢谢,虽然我不确定它是否能满足我的需求,而且它似乎根本无法捕捉字幕。我希望它查看每个电影文件的输出,然后如果输出包含单词“字幕”和/或“章节”,则执行操作,否则跳过。
    • 为了正确解析它,我需要一个你没有提供的字幕样本
    • 以上示例包含视频轨道、2 个音频轨道、2 个字幕轨道和章节
    • 没认出来,我在 line begin 的锚点无法匹配,你希望输出如何?
    • 我真的不需要输出。我只需要根据 mkvmerge 命令的输出检查给定文件是否包含字幕轨道和/或章节。问题是我不熟悉管道或 for 循环。如果是 IF 语句,我会放 OR。
    猜你喜欢
    • 2018-06-14
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 2015-06-26
    • 2016-03-03
    相关资源
    最近更新 更多