如何使用批处理脚本从文本文件中获取唯一字符串
how to get a unique string from a text file using Batch script
我有一个包含以下信息的文本文件:
-host A -P 1
-host A -P 2
-host B -P 1
-host B -P 2
-host B -P 3
-host C -P 1
-host C -P 2
-host A -P 3
现在,我想从批处理脚本中唯一地提取这些主机名。例如,在获取我的数组后应该是这样的:[A B C]
我能够使用以下命令获取这些主机名:
setlocal ENABLEDELAYEDEXPANSION
set /A f=0
if exist "%TEXTFILE%" for /F usebackq^ delims^=^ eol^= %%I in (%TEXTFILE%) do for %%J in (%%I) do (
if /I "%%~J" == "-host" (
set /A f=1
) else (
if !f!==1 (
echo %%J
set /A f=0
)
)
)
我得到以下输出:
A
A
B
B
B
C
C
A
但我只想要唯一的名称。
我们应该如何从文本文件中获取唯一名称?
@echo off
setlocal
for /f "tokens=2" %%a in (test.txt) do set "_%%a=."
for /f "delims=_=" %%a in ('set _') do echo %%a
输出:
A
B
C
第一个for
为每个名字设置一个变量(我们不关心内容)。
第二个 for
列出了这些变量。为此,所有变量都必须以相同的字符开头,并且没有其他变量可以以该字母开头。 set
命令甚至会为您按字母顺序对它们进行排序。
@echo off
setlocal enabledelayedexpansion
set "list=["
for /f "tokens=2" %%a in (test.txt) do set "_%%a=."
for /f "delims=_=" %%a in ('set _') do set "list=!list! %%a"
set "list=%list:[ =[%]"
echo %list%
输出:
[A B C]
下面是一个看起来相当复杂的批处理文件,仅用于 Windows10。该代码使用 sort
命令的新的但未记录的 /unique
选项仅在那个 OS 版本中。 我应该在这里提到 sort
命令不区分大小写,因此 a
和 A
不是唯一的。
它尝试获取前导 -host
单词和任何后续 -P*
单词之间的所有修剪内容。我这样做是为了确保仍会捕获包含空格的字符串。主机名中不允许使用空格,因此您不需要此额外功能,但是,对于一般用途,它可能对您有用。此外,如果您以后希望修改它以用于其他用途,它目前不捕获以连字符开头的子字符串,这在主机名中也是不允许的,(您需要修改 findstr
子-match [^-]
on line 8
to allow for such strings). 最后,如果你的不区分大小写的行前导词不是 -host
,你可以在行 8
,如果您的第二个连字符前导词不是以不区分大小写的字符对 -P
开头,您可以在行 11
.
上修改它
预期的输出应该是一个变量 %array%
,使用您发布的示例,它应该如下所示:
"A","B","C"
如果您不想使用逗号,请将 37
行的 ^,
更改为
。此外,如果您不需要封闭的双引号,请将 35
行上的 "%%I"
更改为 %%I
,并将 37
行上的 "!$:~1!"
更改为 !$:~1!
.
它还应该为每个数组索引项创建单独的变量,格式为 %array[#]%
, 其中 #
是索引号,从零开始,(您可以调整通过将 17
行的 Set "$=-1"
更改为 Set "$=0"
并将 28
行的 array[0]
更改为 array[1]
). 使用您发布的例如,当前代码应生成以下内容:
%array[0]% - expanding to string value A
%array[1]% - expanding to string value B
%array[2]% - expanding to string value C
这里是批处理文件的例子,请记得将%TEXTFILE%
的值调整为完整的,(推荐),或者你的源文件的相对路径在线 3
:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "TEXTFILE=myfile.txt"
Set "$T=%TEMP%$.lst"
If Not Exist "%TEXTFILE%" GoTo :EOF
For /F "Delims==" %%G In ('"(Set array) 2>NUL"') Do Set "%%G="
( For /F Delims^=^ EOL^= %%G In ('Type "%TEXTFILE%" ^|
%SystemRoot%\System32\findstr.exe /RIC:"^-host[ ][ ]*[^-]"') Do (
Set "$=%%G"
SetLocal EnableDelayedExpansion
For /F "Delims=&" %%H In ("!$: -P=&:!") Do (
EndLocal
For /F "Tokens=1,*" %%I In ("%%H") Do Echo %%J
)
)
) 1>"%$T%"
Set "$=-1"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\sort.exe /Unique "%$T%" ^& Del "%$T%"'
) Do (
Set /A $ += 1
SetLocal EnableDelayedExpansion
For %%H In (!$!) Do (
EndLocal
Set "array[%%H]=%%G"
)
)
If Not Defined array[0] GoTo :EOF
For /F "Tokens=1,* Delims=]" %%G In ('"(Set array[) 2>NUL"') Do (
Set "$=%%H"
SetLocal EnableDelayedExpansion
If Not Defined array (
For /F Delims^=^ EOL^= %%I In ("!$:~1!") Do (
EndLocal
Set "array="%%I""
)
) Else For /F UseBackQ^ Delims^=^ EOL^= %%I In ('!array!^,"!$:~1!"') Do (
EndLocal
Set "array=%%I"
)
)
For %%G In (TEXTFILE $T $) Do Set "%%G="
Set array & Pause
包含最后一行只是为了确保您可以看到结果变量及其值。测试后,您可以根据需要将其替换为您自己的代码。
我有一个包含以下信息的文本文件:
-host A -P 1
-host A -P 2
-host B -P 1
-host B -P 2
-host B -P 3
-host C -P 1
-host C -P 2
-host A -P 3
现在,我想从批处理脚本中唯一地提取这些主机名。例如,在获取我的数组后应该是这样的:[A B C]
我能够使用以下命令获取这些主机名:
setlocal ENABLEDELAYEDEXPANSION
set /A f=0
if exist "%TEXTFILE%" for /F usebackq^ delims^=^ eol^= %%I in (%TEXTFILE%) do for %%J in (%%I) do (
if /I "%%~J" == "-host" (
set /A f=1
) else (
if !f!==1 (
echo %%J
set /A f=0
)
)
)
我得到以下输出:
A
A
B
B
B
C
C
A
但我只想要唯一的名称。 我们应该如何从文本文件中获取唯一名称?
@echo off
setlocal
for /f "tokens=2" %%a in (test.txt) do set "_%%a=."
for /f "delims=_=" %%a in ('set _') do echo %%a
输出:
A
B
C
第一个for
为每个名字设置一个变量(我们不关心内容)。
第二个 for
列出了这些变量。为此,所有变量都必须以相同的字符开头,并且没有其他变量可以以该字母开头。 set
命令甚至会为您按字母顺序对它们进行排序。
@echo off
setlocal enabledelayedexpansion
set "list=["
for /f "tokens=2" %%a in (test.txt) do set "_%%a=."
for /f "delims=_=" %%a in ('set _') do set "list=!list! %%a"
set "list=%list:[ =[%]"
echo %list%
输出:
[A B C]
下面是一个看起来相当复杂的批处理文件,仅用于 Windows10。该代码使用 sort
命令的新的但未记录的 /unique
选项仅在那个 OS 版本中。 我应该在这里提到 sort
命令不区分大小写,因此 a
和 A
不是唯一的。
它尝试获取前导 -host
单词和任何后续 -P*
单词之间的所有修剪内容。我这样做是为了确保仍会捕获包含空格的字符串。主机名中不允许使用空格,因此您不需要此额外功能,但是,对于一般用途,它可能对您有用。此外,如果您以后希望修改它以用于其他用途,它目前不捕获以连字符开头的子字符串,这在主机名中也是不允许的,(您需要修改 findstr
子-match [^-]
on line 8
to allow for such strings). 最后,如果你的不区分大小写的行前导词不是 -host
,你可以在行 8
,如果您的第二个连字符前导词不是以不区分大小写的字符对 -P
开头,您可以在行 11
.
预期的输出应该是一个变量 %array%
,使用您发布的示例,它应该如下所示:
"A","B","C"
如果您不想使用逗号,请将 37
行的 ^,
更改为
。此外,如果您不需要封闭的双引号,请将 35
行上的 "%%I"
更改为 %%I
,并将 37
行上的 "!$:~1!"
更改为 !$:~1!
.
它还应该为每个数组索引项创建单独的变量,格式为 %array[#]%
, 其中 #
是索引号,从零开始,(您可以调整通过将 17
行的 Set "$=-1"
更改为 Set "$=0"
并将 28
行的 array[0]
更改为 array[1]
). 使用您发布的例如,当前代码应生成以下内容:
%array[0]% - expanding to string value A
%array[1]% - expanding to string value B
%array[2]% - expanding to string value C
这里是批处理文件的例子,请记得将%TEXTFILE%
的值调整为完整的,(推荐),或者你的源文件的相对路径在线 3
:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "TEXTFILE=myfile.txt"
Set "$T=%TEMP%$.lst"
If Not Exist "%TEXTFILE%" GoTo :EOF
For /F "Delims==" %%G In ('"(Set array) 2>NUL"') Do Set "%%G="
( For /F Delims^=^ EOL^= %%G In ('Type "%TEXTFILE%" ^|
%SystemRoot%\System32\findstr.exe /RIC:"^-host[ ][ ]*[^-]"') Do (
Set "$=%%G"
SetLocal EnableDelayedExpansion
For /F "Delims=&" %%H In ("!$: -P=&:!") Do (
EndLocal
For /F "Tokens=1,*" %%I In ("%%H") Do Echo %%J
)
)
) 1>"%$T%"
Set "$=-1"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\sort.exe /Unique "%$T%" ^& Del "%$T%"'
) Do (
Set /A $ += 1
SetLocal EnableDelayedExpansion
For %%H In (!$!) Do (
EndLocal
Set "array[%%H]=%%G"
)
)
If Not Defined array[0] GoTo :EOF
For /F "Tokens=1,* Delims=]" %%G In ('"(Set array[) 2>NUL"') Do (
Set "$=%%H"
SetLocal EnableDelayedExpansion
If Not Defined array (
For /F Delims^=^ EOL^= %%I In ("!$:~1!") Do (
EndLocal
Set "array="%%I""
)
) Else For /F UseBackQ^ Delims^=^ EOL^= %%I In ('!array!^,"!$:~1!"') Do (
EndLocal
Set "array=%%I"
)
)
For %%G In (TEXTFILE $T $) Do Set "%%G="
Set array & Pause
包含最后一行只是为了确保您可以看到结果变量及其值。测试后,您可以根据需要将其替换为您自己的代码。