我正在尝试从一系列文本文件(字幕文件)中的特定行中提取位于第一个和第二个逗号之间的字符串。文本文件的格式如下:
Subtitles01.txt
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: Default, Estrangelo Edessa, 57, &H00FFFFFF
Style: Title1, Arno Pro, 65, &H00606066
Subtitles02.txt
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: OP Eng, Arno Pro, 45, &H00100F11
Style: ED Romaji, Nueva Std Cond, 46, &H00FFFFFF
Subtitles03.txt
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: OP Eng, Estrangelo Edessa, 45, &H00100F11
Style: Default, Arno Pro, 45, &H00100F11
Style: ED Romaji, Nueva Std Cond, 46, &H00FFFFFF
我想在这里实现的是为以“Style:”开头的每一行提取Fontname,然后以非重复的方式确定哪些字幕包含我想要的字体。因此,最终结果将输出到文本文件,如下所示;
Subtitles01.txt: Estrangelo Edessa
Subtitles01.txt: Arno Pro
Subtitles02.txt: Arno Pro
Subtitles02.txt: Nueva Std Cond
Subtitles03.txt: Estrangelo Edessa
Subtitles03.txt: Arno Pro
Subtitles03.txt: Nueva Std Cond
Only Subtitles03.txt is needed.
由于Subtitles03.txt包含Subtitles01.txt和Subtitles02.txt中的所有字体,因此只需要Subtitles03.txt。目标是使用最少量的文件来查找所有文件中的唯一字体。我已经提出了以下批处理脚本,使用 findstr 来提取以“Style:”开头的行,但我已经超出了这个范围。
@echo off
findstr /B /C:"Style:" *.txt > results.txt
if %errorlevel%==0 (
echo Found! logged files into results.txt
) else (
echo No matches found
)
任何帮助将不胜感激。谢谢你们!
答案 0 :(得分:1)
修改:使用以下内容:
^Style:\s*([^,]+)\s*,\s*([^,]+)\s*,\s*([^,]+)\s*,\s*(.+)\s*
答案 1 :(得分:1)
我意识到你显然是在一个默认没有安装awk
或Perl的平台上,但你可能仍然想考虑安装其中一个工具,特别是如果你需要在将来
awk -F, '/^Style:/ { print FILENAME ":" $2 }' *.txt
或者使用Perl:
perl -ne 'print "$ARGV:$1\n" if m/^Style: [^,]*,([^,]*)/' *.txt
随后的优化(删除与其他匹配文件重叠的任何文件)在任何一种语言中都不难做到。 Perl可以更好地扩展到更大和更多样化的任务,所以如果你不熟悉它们,那将是我的第一个推荐(以更长,更崎岖的学习曲线为代价,然后你也应该考虑Python)。
答案 2 :(得分:1)
我想除了批处理之外使用其他语言会更容易,或者至少使用非本机实用程序。但这是纯粹的原生批量解决方案。
我不知道FINDSTR正则表达式如何帮助解决这个问题。它不能像许多其他非本地批处理正则表达式实用程序一样提取匹配行的一部分。
您可以使用FOR / F从每个文件中提取字体:
for /f "tokens=2 delims=," %%A in ('findstr /lb "Style:" file.txt') do echo font=%%A
您可以使用环境变量来提供唯一字体列表。使用变量名称中的字体名称定义变量,所有变量都以font_
为前缀。只能为给定名称定义一个变量。指定的值无关紧要。然后,您可以使用set font_
列出所有唯一的字体名称。可以计算唯一名称的数量,或者可以解析实际的字体名称(删除font_
前缀)。
棘手的部分是建立覆盖整套唯一字体名称所需的最小文件集。我想有人可以提出一个有效的解决方案。我刚刚使用了强力递归排列方法:我计算每个排列中找到的唯一字体的数量,并将数字与唯一字体的总数进行比较。如果我已经找到比当前集合更小的完整集,我已经添加了一些快捷方式,以便不按特定的排列路径进行。
如果我在递归中使用SETLOCAL,代码可能会更简单,但批处理仅限于32级SETLOCAL。我想要一个可以支持超过32个文件的解决方案,尽管我对这么多文件的性能有点担心。
编辑 - 我修复了我的:permuteFiles
例程中的一个错误,该错误在我有超过3个文件后出现
@echo off
setlocal enableDelayedExpansion
::Make sure there are no font_ variables defined
for /f "delims==" %%A in ('set font_ 2^>nul') do set "%%A="
::Read all the Subtitle files and
:: - create an "array" of file names
:: - create a file of font names for each input file
:: - create an "associative array" of unique font names
:: - List the available file/font pairs in the final results
:: - List the unique fonts in the final results
set fileCount=0
>results.txt (
echo Available fonts
echo ----------------------------
for %%F in (subtitles*.txt) do (
set /a totalFiles+=1
set "file_!totalFiles!=%%F"
3>"%%F.fonts" (
for /f "tokens=2 delims=," %%A in ('findstr /lb "Style:" "%%F"') do (
set "font_%%A=1"
>&3 echo %%A
echo %%F:%%A
)
)
)
echo(
echo Unique fonts
echo ----------------------------
for /f "delims==" %%A in ('set font_') do (
set "font=%%A"
echo !font:~5!
)
)
::Count the number of unique fonts
for /f %%N in ('set font_ ^| find /c /v ""') do set uniqueFonts=%%N
::Test all the permutations
set /a minFileCount=%totalFiles%+1
for /l %%N in (1 1 %totalFiles%) do (
call :permuteFiles %%N 0 ""
)
::List the required files in the final results
>>results.txt (
echo(
echo The following files contain the complete set of unique fonts:
echo -------------------------------------------------------------
for %%N in (%minFileList:~1,-1%) do echo !file_%%N!
)
type results.txt
::Cleanup
del subtitles*.txt.fonts
exit /b
:permuteFiles fileNumber fileCount fileList
if %1==%totalFiles% (
if %2 gtr 0 call :testPermutation %2 %3
set /a fileCount=%2+1
if !fileCount! lss !minFileCount! call :testPermutation !fileCount! "%~3,%1"
) else (
set /a nextFile=%1+1
if %2 gtr 0 call :permuteFiles !nextFile! %2 %3
set /a "nextFile=%1+1, fileCount=%2+1"
if !fileCount! lss !minFileCount! call :permuteFiles !nextFile! !fileCount! "%~3,%1"
)
exit /b
:testPermutation fileCount fileList
for /f "delims==" %%A in ('set font_ 2^>nul') do set "%%A="
for %%N in (%~2) do (
for /f "usebackq delims=" %%A in ("!file_%%N!.fonts") do set "font_%%A=1"
)
for /f %%N in ('set font_ ^| find /c /v ""') do if %%N==%uniqueFonts% (
set minFileList=%2
set minFileCount=%1
)
exit /b
以下是使用示例输入的结果:
Available fonts
----------------------------
Subtitles01.txt: Estrangelo Edessa
Subtitles01.txt: Arno Pro
Subtitles02.txt: Arno Pro
Subtitles02.txt: Nueva Std Cond
subtitles03.txt: Estrangelo Edessa
subtitles03.txt: Arno Pro
subtitles03.txt: Nueva Std Cond
Unique fonts
----------------------------
Arno Pro
Estrangelo Edessa
Nueva Std Cond
The following files contain the complete set of unique fonts:
-------------------------------------------------------------
subtitles03.txt
答案 3 :(得分:1)
如果“目标是使用最少量的文件来查找所有文件中的唯一字体”,则下面的批处理文件可以解决您的问题:
编辑:行动!我之前的代码中有一个小错误:在处理目标文件中包含的每个Fontname时,我不应该删除整个文件,只需从文件计数中减去那个字体名称。我修复了下面代码中的错误(现在确实更简单):
@echo off
setlocal EnableDelayedExpansion
rem Create "Files with Fontnames" and "Fontnames in Files" sets,
rem and FileCount with number of Fontnames in each file
for %%a in (*.txt) do (
for /F "tokens=2 delims=," %%b in ('findstr /B /C:"Style:" %%a') do (
set File[%%~Na]=!File[%%~Na]!"%%b",
set Fontname[%%b]=!Fontname[%%b]!%%~Na,
set /A FileCount[%%~Na]+=1
)
)
echo Fonts by File:
set File[
echo/
echo/
echo Following files provide all fonts:
rem For each non-processed "File with Fontnames"
:nextFile
rem Process File with larger number of Fontnames first
set fontCount=0
for /F "tokens=2,3 delims=[]=" %%a in ('set FileCount[') do (
if %%b gtr !fontcount! (
set fontCount=%%b
set nextFile=%%a
)
)
if %fontCount% equ 0 goto exit
rem Show this file as result
echo File %nextFile%.txt
rem For each Fontname in this file
for %%a in (!File[%nextFile%]!) do (
rem Subtract this Fontname from the Files that include it
for %%b in (!Fontname[%%~a]!) do (
set /A FileCount[%%b]-=1
rem and delete this Fontname
set Fontname[%%~a]=
)
)
rem Go back to process next file
goto nextFile
:exit
例如:
Fonts by File:
File[Subtitles01]=" Estrangelo Edessa"," Arno Pro",
File[Subtitles02]=" Arno Pro"," Nueva Std Cond",
File[Subtitles03]=" Estrangelo Edessa"," Arno Pro"," Nueva Std Cond",
Following files provide all fonts:
File Subtitles03.txt
答案 4 :(得分:0)
Style: (.*),(.*),(.*),(.*)
然后,获得第二个匹配的结果。只需确保使用整个字符串即可。不只是从括号开始。
修改强>
抱歉,我错过了实际上有四个块,有三个逗号,而不是三个块,有两个逗号。代码现在正在运行并修复。