我正在处理批处理文件并导出到文本文件。看起来一切都很好,但是当我打开文本文件时,许多新行中断。所以,我想删除它们。
@echo OFF
setlocal EnableDelayedExpansion
(
systeminfo |findstr /c:"Host Name" /c:"OS Name" /c:"OS Version" /c:"Original Install Date" /c:"System Manufacturer" /c:"System Model" /c:"System Type" /c:"Total Physical Memory"
wmic bios get serialnumber /Format:list | more | findstr .
wmic cpu get name /Format:list | more | findstr .
echo=%userdomain%\%username%
)> %ComputerName%.txt
结果文本文件没问题,但仍然有很多新行中断,我想删除它们
Host Name: PGV-PF165HNN
OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.18363 N/A Build 18363
Original Install Date: 7/22/2019, 6:28:01 PM
System Manufacturer: LENOVO
System Model: 20JM0009US
System Type: x64-based PC
BIOS Version: LENOVO N1QET87W (1.62 ), 2/27/2020
Total Physical Memory: 8,072 MB
SerialNumber=PF165HNN
Name=Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
WINDOM1\brian.lee
%SystemRoot%\System32\systeminfo.exe
的操作系统语言相关输出是采用 ASCII/ANSI/OEM 的字符编码,这意味着使用在命令提示符窗口中运行时显示的代码页每个字符一个字节chcp
。代码页取决于为用于运行批处理文件的帐户配置的国家(地区)。只要感兴趣的数据不包含代码值大于 127 的字符(非 ASCII 字符),代码页并不重要。
经
systeminfo
过滤的 findstr
的输出是二进制文件,冒号左侧为文件中的十六进制偏移量、字节的十六进制值以及分号后的 ASCII 表示形式:
0000h: 48 6F 73 74 20 4E 61 6D 65 3A 20 20 20 20 20 20 ; Host Name:
0010h: 20 20 20 20 20 20 20 20 20 20 20 50 47 56 2D 50 ; PGV-P
0020h: 46 31 36 35 48 4E 4E 0D 0A 4F 53 20 4E 61 6D 65 ; F165HNN..OS Name
0030h: 3A 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; :
0040h: 20 20 20 20 4D 69 63 72 6F 73 6F 66 74 20 57 69 ; Microsoft Wi
0050h: 6E 64 6F 77 73 20 31 30 20 50 72 6F 0D 0A 4F 53 ; ndows 10 Pro..OS
0060h: 20 56 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 ; Version:
0070h: 20 20 20 20 20 20 20 20 20 31 30 2E 30 2E 31 38 ; 10.0.18
0080h: 33 36 33 20 4E 2F 41 20 42 75 69 6C 64 20 31 38 ; 363 N/A Build 18
0090h: 33 36 33 0D 0A 4F 72 69 67 69 6E 61 6C 20 49 6E ; 363..Original In
00a0h: 73 74 61 6C 6C 20 44 61 74 65 3A 20 20 20 20 20 ; stall Date:
00b0h: 37 2F 32 32 2F 32 30 31 39 2C 20 36 3A 32 38 3A ; 7/22/2019, 6:28:
00c0h: 30 31 20 50 4D 0D 0A 53 79 73 74 65 6D 20 4D 61 ; 01 PM..System Ma
00d0h: 6E 75 66 61 63 74 75 72 65 72 3A 20 20 20 20 20 ; nufacturer:
00e0h: 20 20 4C 45 4E 4F 56 4F 0D 0A 53 79 73 74 65 6D ; LENOVO..System
00f0h: 20 4D 6F 64 65 6C 3A 20 20 20 20 20 20 20 20 20 ; Model:
0100h: 20 20 20 20 20 32 30 4A 4D 30 30 30 39 55 53 0D ; 20JM0009US.
0110h: 0A 53 79 73 74 65 6D 20 54 79 70 65 3A 20 20 20 ; .System Type:
0120h: 20 20 20 20 20 20 20 20 20 20 20 20 78 36 34 2D ; x64-
0130h: 62 61 73 65 64 20 50 43 0D 0A 42 49 4F 53 20 56 ; based PC..BIOS V
0140h: 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 20 20 ; ersion:
0150h: 20 20 20 20 20 4C 45 4E 4F 56 4F 20 4E 31 51 45 ; LENOVO N1QE
0160h: 54 38 37 57 20 28 31 2E 36 32 20 29 2C 20 32 2F ; T87W (1.62 ), 2/
0170h: 32 37 2F 32 30 32 30 0D 0A 54 6F 74 61 6C 20 50 ; 27/2020..Total P
0180h: 68 79 73 69 63 61 6C 20 4D 65 6D 6F 72 79 3A 20 ; hysical Memory:
0190h: 20 20 20 20 38 2C 30 37 32 20 4D 42 0D 0A ; 8,072 MB..
%SystemRoot%\System32\wbem\wmic.exe
的输出始终使用UTF-16Little Endian编码和字节顺序标记(BOM)进行Unicode编码。因此,两个使用的 wmic
命令行的输出是每个字符两个字节。
命令行
wmic bios get serialnumber /Format:list
产生二进制输出:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 53 00 65 00 72 00 ; ÿþ........S.e.r.
0010h: 69 00 61 00 6C 00 4E 00 75 00 6D 00 62 00 65 00 ; i.a.l.N.u.m.b.e.
0020h: 72 00 3D 00 50 00 46 00 31 00 36 00 35 00 48 00 ; r.=.P.F.1.6.5.H.
0030h: 4E 00 4E 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; N.N.............
前两个字节
FF FE
是UTF-16 Little Endian的字节顺序标记。每个 ASCII 字符由两个字节(16 位)编码,高字节值为 0。换行符为回车符 (0D 00) 和换行符 (0A 00)。首先输出两个空行,然后是包含感兴趣数据的行,最后再次输出两个空行。
命令行
wmic cpu get name
产生二进制输出:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 4E 00 61 00 6D 00 ; ÿþ........N.a.m.
0010h: 65 00 3D 00 49 00 6E 00 74 00 65 00 6C 00 28 00 ; e.=.I.n.t.e.l.(.
0020h: 52 00 29 00 20 00 43 00 6F 00 72 00 65 00 28 00 ; R.). .C.o.r.e.(.
0030h: 54 00 4D 00 29 00 20 00 69 00 35 00 2D 00 36 00 ; T.M.). .i.5.-.6.
0040h: 33 00 30 00 30 00 55 00 20 00 43 00 50 00 55 00 ; 3.0.0.U. .C.P.U.
0050h: 20 00 40 00 20 00 32 00 2E 00 34 00 30 00 47 00 ; .@. .2...4.0.G.
0060h: 48 00 7A 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; H.z.............
Unicode 输出通过
cmd.exe
处理批处理文件重定向到 more
,现在输出行每个字符一个字节。但是 Windows 命令处理器在解释 UTF-16 LE 编码行时有一个错误,可以在使用以下命令行时看到:
wmic bios get serialnumber /Format:list | more >output.txt
文件
output.txt
包含二进制字节:
0000h: 0D 0D 0A 0D 0D 0A 53 65 72 69 61 6C 4E 75 6D 62 ; ......SerialNumb
0010h: 65 72 3D 50 46 31 36 35 48 4E 4E 0D 0D 0A 0D 0D ; er=PF165HNN.....
0020h: 0A 0D 0D 0A 0D 0A 0D 0A ; ........
每个 Unicode 编码的回车 + 换行 (0D 00 0A 00) 都会变成 ASCII 编码的回车 + 回车 + 换行 (0D 0D 0A)。
这才是真正的问题。使用正则表达式搜索字符串
.
来匹配具有至少一个字符的所有行,以及在从 Unicode 转换为 ASCII 的输出中空行与此正则表达式搜索字符串匹配时,额外的回车结果会不正确。
这取决于所使用的文本编辑器如何解释无效的换行符序列。大多数文本编辑器将不带换行的回车解释为行终止,但
findstr
不会这样做。
一种解决方案是显式搜索包含感兴趣数据的行。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE | %SystemRoot%\System32\findstr.exe /L /C:SerialNumber
%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE | %SystemRoot%\System32\findstr.exe /L /C:Name
echo %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
写入文件
%ComputerName%.txt
的数据完全以 ASCII 编码,各处仅使用 0D 0A
作为行终止符。
有关代码小更改的一些附加信息:
more
被省略,因为实际上并不需要。从 Unicode 到 ASCII 的不正确转换是由 Windows 命令处理器完成的 cmd.exe
。cmd.exe
不必使用环境变量 PATHEXT
和 PATH
的值来搜索可执行文件。/Format:list
被选项 /VALUE
替换,这会产生相同的输出。/L
运行,以明确指示 findstr
运行文字搜索,尽管这是使用选项 /C:
的默认设置。更好的批处理文件代码是:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
echo Domain\User Name: %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
使用 WMIC 确定并使用 ECHO 输出的附加数据以与
systeminfo
的输出相同的格式写入文本文件。
注意: 最后一个
echo
命令行在环境变量 USERDOMAIN
的值或环境变量 USERNAME
包含 )
或 &
的情况下不安全。 100% 安全的是:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
) >"%ComputerName%.txt"
setlocal EnableDelayedExpansion
echo Domain\User Name: !USERDOMAIN!\!USERNAME!>>"%ComputerName%.txt"
endlocal
endlocal
要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
echo /?
endlocal /?
findstr /?
for /?
if /?
setlocal /?
systeminfo /?
wmic /?
wmic bios /?
wmic bios get /?
wmic cpu /?
wmic cpu get /?
你可以试试这个吗: 使用以下代码创建 sysi.vbs 文件并按以下方式运行: cscript //nologo sysi.vbs
根据需要进行调整。
sysi.vbs: '--------------------------------------------------------
Set dtmConvertedDate = CreateObject("WbemScripting.SWbemDateTime")
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
' Create a new WshNetwork object to access network properties.
Wscript.Echo "*** from WScript.Network ***************"
Set WshNetwork = WScript.CreateObject("WScript.Network")
Wscript.Echo "Computer name : " & WshNetwork.ComputerName
Wscript.Echo "Domain : " & WshNetwork.UserDomain
Wscript.Echo "User name : " & WshNetwork.UserName
Wscript.Echo "*** from Win32_OperatingSystem **************"
For Each objOperatingSystem in colOperatingSystems
Wscript.Echo "OS Caption: " & objOperatingSystem.Caption
Wscript.Echo "OS Version: " & objOperatingSystem.Version
dtmConvertedDate.Value = objOperatingSystem.InstallDate
dtmInstallDate = dtmConvertedDate.GetVarDate
Wscript.Echo "OS Install Date: " & dtmInstallDate
Wscript.Echo "OS Serial Number: " & objOperatingSystem.SerialNumber
Next
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)
Wscript.Echo "*** from Win32_ComputerSystem **********"
For Each objItem in colItems
Wscript.Echo "Manufacturer: " & objItem.Manufacturer
Wscript.Echo "Model: " & objItem.Model
Wscript.Echo "SystemType: " & objItem.SystemType
Wscript.Echo "TotalPhysicalMemory: " & objItem.TotalPhysicalMemory
Next
Wscript.Echo "*** from Win32_Processor **********"
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor",,48)
For Each objItem in colItems
Wscript.Echo "Proc Name: " & objItem.Name
Wscript.Echo "CurrentClockSpeed: " & objItem.CurrentClockSpeed
Wscript.Echo "ErrorDescription: " & objItem.ErrorDescription
Wscript.Echo "DeviceID: " & objItem.DeviceID
Wscript.Echo "Manufacturer: " & objItem.Manufacturer
Wscript.Echo "MaxClockSpeed: " & objItem.MaxClockSpeed
Next
Wscript.Echo "*** from Win32_BIOS ******* "
Set colBIOS = objWMIService.ExecQuery("Select * from Win32_BIOS")
Set dtmRelDateRaw = CreateObject("WbemScripting.SWbemDateTime")
For each objBIOS in colBIOS
Wscript.Echo "BIOS Name: " & objBIOS.Name
Wscript.Echo "BIOS Manufacturer: " & objBIOS.Manufacturer
Wscript.Echo "Primary BIOS: " & objBIOS.PrimaryBIOS
dtmRelDateRaw.Value = objBIOS.ReleaseDate
dtmRelDate = dtmRelDateRaw.GetVarDate
Wscript.Echo "Release Date: " & objBIOS.ReleaseDate
Wscript.Echo "Release Date: " & dtmRelDate
Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
Wscript.Echo "Status: " & objBIOS.Status
Wscript.Echo "Version: " & objBIOS.Version
Next
只是不使用
DisableDelayedExpansion
的替代方法:
@echo off && setlocal EnableDelayedExpansion
set "_usrd=Domain\User Name: !USERDOMAIN!\!USERNAME!" && set "_bios=Bios Serial Number: -x" && set "_CPUs=CPU Name: -y"
set "_wmic=%SystemRoot%\System32\wbem\wmic.exe" && pushd "%SystemRoot%\System32" && >"%temp%\%ComputerName%.txt" 2>nul (
systeminfo.exe | findstr "Host.Name OS.Name OS.Version Original.Install.Date System.Manufacturer System.Model System.Type Total.Physical.Memory"
for /f skip^=1^tokens^=* %%i in ('!_wmic! bios get serialnumber^|findstr "[0-9] [aZ]"')do ^< nul call set /p "'=!_bios:-x= %%~i!" <nul & echo\
for /f skip^=1^tokens^=* %%j in ('!_wmic! cpu get name^|findstr "[0-9] [aZ]"')do ^< nul call set /p "'=!_CPUs:-y= %%~j!" <nul & echo\
echo\!_usrd! ) && type "%temp%\%ComputerName%.txt" && popd && endlocal && goto :EOF
Host Name: LAME_SLUG
OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.18363 N/A Build 18363
Original Install Date: 3/27/2020, 11:17:06 PM
System Manufacturer: LENOVO
System Model: 80YH
System Type: x64-based PC
BIOS Version: LENOVO 4WCN46WW, 12/30/2019
Total Physical Memory: 16,259 MB
Bios Serial Number: PE03A187
CPU Name: Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
Domain\User Name: LAME_SLUG\ecker