批处理脚本:提取文本 after/before last/first 出现的字符并将其存储在数组中
Batch script: extract text after/before last/first occurrence of characters and store it in array
假设我的文件“%userprofile%\~.txt”下有以下内容:
Monitor: Generic PnP Monitor
Device: \.\DISPLAY1
Adapter: Intel(R) UHD Graphics 630
(1920 x 1080 x 32 bpp) 60Hz default up, attached (-1920,0)
Monitor: Generic PnP Monitor
Device: \.\DISPLAY4
Adapter: NVIDIA Quadro P2000
(1280 x 1024 x 32 bpp) 60Hz default up, attached (1920,0)
Monitor: Generic PnP Monitor
Device: \.\DISPLAY8
Adapter: DisplayLink USB Device
(1920 x 1080 x 32 bpp) 60Hz default up, attached, primary (0,0)
文本块的数量可能会有所不同。
我要获取的是每块最后一行出现的两个坐标中的第一个,所以根据例子,结果应该是:
-1920
1920
0
为了在批处理脚本中执行此操作,我首先通过初始 for 循环分析文件,该循环检索包含字符串“default up, attached”的行。
然后对于每个检索到的字符串,我搜索最后一次出现 (
之后的文本。
根据之前的结果,我搜索了第一次出现 ,
之前的文本。
我找到了一个在 for 循环之外工作的解决方案(请参阅下面标有 **
的行),但我希望这些行在循环内。我尝试了下面标有 *
的行,但脚本退出了,我不知道错误是什么。希望是一个微不足道的缺失部分。请原谅我的批处理脚本知识不多。
我的脚本:
@echo off
setlocal EnableDelayedExpansion
set Cnt=0
FOR /F "tokens=*" %%a IN ('findstr "default up, attached" "%userprofile%\~.txt"') DO (
set /a Cnt+=1
set result=%%a
for %%b in ("%result:(=" "%") do set "result=%%~b" <= * THESE LINES DON'T WORK!!!
for /f "tokens=1 delims=," %%c in ("%result%") do set "result=%%~c" <= * THESE LINES DON'T WORK!!!
call Set Monitors[%%Cnt%%]=!result!
)
for %%b in ("%Monitors[1]:(=" "%") do set "Monitors[1]=%%~b" <= ** THESE LINES WORK
for %%b in ("%Monitors[2]:(=" "%") do set "Monitors[2]=%%~b" <= ** THESE LINES WORK
for %%b in ("%Monitors[3]:(=" "%") do set "Monitors[3]=%%~b" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[1]%") do set "Monitors[1]=%%~c" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[2]%") do set "Monitors[2]=%%~c" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[3]%") do set "Monitors[3]=%%~c" <= ** THESE LINES WORK
echo %Monitors[1]%
echo %Monitors[2]%
echo %Monitors[3]%
pause
另一种方法是使用 powershell 正则表达式来执行此操作:
@Echo off
:# Replace with actual filename
Set "File=%~dp0in.txt"
Set "Content=\(-?\d+,\d+\)$"
Set "Prefix=^.*?,+ \w+ \("
Set "Suffix=,\d*\)"
:# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.1
Set "[i]=1"
For /f "Delims=" %%G in ('
powershell -nologo -noprofile -c ^
"(GC "%File%") -match '%Content%' | ForEach {"$_" -replace '%Prefix%' -replace '%Suffix%'}
')Do Call Set /A "[i]+=1","Monitor[%%[i]%%]=%%G"
Set Monitor[
Goto :Eof
您可以使用括号和逗号作为分隔符来获取所需的值。因为您的输入行之一中有额外的逗号,所以这将需要两个嵌套的 FOR
命令。第一个 FOR
将用括号将其分开,并为您提供第二组括号之间的所有内容。然后将该输出放入另一个 FOR
命令以在逗号处拆分值。
@echo off
REM use the parentheses as a delimiter
FOR /F "tokens=3 delims=()" %%G IN ('findstr "default up, attached" "file.txt"') DO (
REM USE the comma as a delimiter for the final split up of the variable.
FOR /F "TOKENS=1 delims=," %%H IN ("%%~G") DO ECHO %%~H
)
假设我的文件“%userprofile%\~.txt”下有以下内容:
Monitor: Generic PnP Monitor
Device: \.\DISPLAY1
Adapter: Intel(R) UHD Graphics 630
(1920 x 1080 x 32 bpp) 60Hz default up, attached (-1920,0)
Monitor: Generic PnP Monitor
Device: \.\DISPLAY4
Adapter: NVIDIA Quadro P2000
(1280 x 1024 x 32 bpp) 60Hz default up, attached (1920,0)
Monitor: Generic PnP Monitor
Device: \.\DISPLAY8
Adapter: DisplayLink USB Device
(1920 x 1080 x 32 bpp) 60Hz default up, attached, primary (0,0)
文本块的数量可能会有所不同。
我要获取的是每块最后一行出现的两个坐标中的第一个,所以根据例子,结果应该是:
-1920
1920
0
为了在批处理脚本中执行此操作,我首先通过初始 for 循环分析文件,该循环检索包含字符串“default up, attached”的行。
然后对于每个检索到的字符串,我搜索最后一次出现 (
之后的文本。
根据之前的结果,我搜索了第一次出现 ,
之前的文本。
我找到了一个在 for 循环之外工作的解决方案(请参阅下面标有 **
的行),但我希望这些行在循环内。我尝试了下面标有 *
的行,但脚本退出了,我不知道错误是什么。希望是一个微不足道的缺失部分。请原谅我的批处理脚本知识不多。
我的脚本:
@echo off
setlocal EnableDelayedExpansion
set Cnt=0
FOR /F "tokens=*" %%a IN ('findstr "default up, attached" "%userprofile%\~.txt"') DO (
set /a Cnt+=1
set result=%%a
for %%b in ("%result:(=" "%") do set "result=%%~b" <= * THESE LINES DON'T WORK!!!
for /f "tokens=1 delims=," %%c in ("%result%") do set "result=%%~c" <= * THESE LINES DON'T WORK!!!
call Set Monitors[%%Cnt%%]=!result!
)
for %%b in ("%Monitors[1]:(=" "%") do set "Monitors[1]=%%~b" <= ** THESE LINES WORK
for %%b in ("%Monitors[2]:(=" "%") do set "Monitors[2]=%%~b" <= ** THESE LINES WORK
for %%b in ("%Monitors[3]:(=" "%") do set "Monitors[3]=%%~b" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[1]%") do set "Monitors[1]=%%~c" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[2]%") do set "Monitors[2]=%%~c" <= ** THESE LINES WORK
for /f "tokens=1 delims=," %%c in ("%Monitors[3]%") do set "Monitors[3]=%%~c" <= ** THESE LINES WORK
echo %Monitors[1]%
echo %Monitors[2]%
echo %Monitors[3]%
pause
另一种方法是使用 powershell 正则表达式来执行此操作:
@Echo off
:# Replace with actual filename
Set "File=%~dp0in.txt"
Set "Content=\(-?\d+,\d+\)$"
Set "Prefix=^.*?,+ \w+ \("
Set "Suffix=,\d*\)"
:# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.1
Set "[i]=1"
For /f "Delims=" %%G in ('
powershell -nologo -noprofile -c ^
"(GC "%File%") -match '%Content%' | ForEach {"$_" -replace '%Prefix%' -replace '%Suffix%'}
')Do Call Set /A "[i]+=1","Monitor[%%[i]%%]=%%G"
Set Monitor[
Goto :Eof
您可以使用括号和逗号作为分隔符来获取所需的值。因为您的输入行之一中有额外的逗号,所以这将需要两个嵌套的 FOR
命令。第一个 FOR
将用括号将其分开,并为您提供第二组括号之间的所有内容。然后将该输出放入另一个 FOR
命令以在逗号处拆分值。
@echo off
REM use the parentheses as a delimiter
FOR /F "tokens=3 delims=()" %%G IN ('findstr "default up, attached" "file.txt"') DO (
REM USE the comma as a delimiter for the final split up of the variable.
FOR /F "TOKENS=1 delims=," %%H IN ("%%~G") DO ECHO %%~H
)