我有一个文本文件,其中包含从PowerShell脚本传输的数据。数据是域笔记本电脑上BitLocker的状态。文本文件包含的示例如下:
var str = "10M225S"
var m = str.split("M")[0];
var s = str.split("M")[1].split("S")[0];
console.log("m >>> " + m);
console.log("s >>> " + s);
我正在寻找的是一个脚本,它将搜索两个特定行彼此相邻的所有实例。因此,例如,在文本文件中,我需要脚本来查找行的位置"转换状态:完全加密"和"保护状态:保护关闭"是。然后,一旦满足该要求,则需要将位于这两行之上的计算机的名称回显或传送到文本文件中。在上面的例子中,它将是Computer2。需要考虑的一件事是,某些系统有多个硬盘驱动器或分区,它们具有不同的BitLocker状态。因此,在上面的示例中,一个系统可能在文本文件中有两个条目,如Computer3。
我想要的最终结果是一个文本文件,其中只包含具有"转换状态:完全加密"的计算机名称。和"保护状态:保护关闭"作为他们的国家。我的脚本技能非常有限,但我能够搞清楚这些事情。这个让我和我合作的其他管理员一样难过。任何帮助或方向将不胜感激。
答案 0 :(得分:1)
我过去常常不回答那些没有表现出来自OP的努力的问题;但是,这个问题很有意思!
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (input.txt) do (
set "line=%%a"
for /F "tokens=1,2 delims=:" %%b in ("!line: =!") do (
if "%%b" equ "ComputerName" set "ConversionStatus="
if "%%b" equ "ConversionStatus" set "ProtectionStatus="
set "%%b=%%c"
)
if "!ConversionStatus!+!ProtectionStatus!" equ "FullyEncrypted+ProtectionOff" (
echo !ComputerName!
)
)
答案 1 :(得分:0)
如果您希望逐行处理文件并根据多行的内容执行某些操作,则需要记住/保持之前看到的行的状态。要评估可能复杂的布尔表达式(看到这个或那个但不是这个......),Select Case True/False
会派上用场。
演示代码:
Option Explicit
Function qq(s) : qq = """" & s & """" : End Function
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oTS : Set oTS = oFS.OpenTextFile("..\data\41145072.txt")
Dim sLine, aParts, sKey, sVal, sCom, sCon, sProt
Do Until oTS.AtEndOfStream
sLine = oTS.ReadLine()
aParts = Split(sLine, ":")
If 1 = UBound(aParts) Then
sKey = Left(sLine, 3)
sVal = Trim(aParts(1))
' WScript.Echo qq(sLine), qq(sVal)
Select Case True
Case sKey = "Com"
sCom = sVal
Case sKey = "Con"
sCon = sVal
Case sKey = "Pro" And sCon = "Fully Encrypted" And sVal = "Protection Off"
WScript.Echo "****", sCom, sCon, sVal
End Select
Else
WScript.Echo oTS.Line, qq(sLine), "Parse Error"
End If
Loop
oTS.Close
输出:
cscript 41145072.vbs
**** Computer2 Fully Encrypted Protection Off
答案 2 :(得分:0)
包含两个RegExes的PowerShell解决方案。
第一个将文件拆分为以Computer Name
第二个使用命名的捕获组来grep计算机名称并检查条件。
$InFile = ".\41145072.txt"
$Delimiter = 'Computer Name:'
$Escaped = [regex]::Escape($Delimiter)
$Split = "(?!^)(?=$Escaped)"
$Search = [RegEx]'(?smi)Computer Name:\s+(?<ComputerName>[0-9a-z_-]+).*Fully Encrypted\r\nProtection Status:\s+Protection Off'
(Get-Content $InFile -Raw) -split $Split | ForEach-Object {
If ($_ -match $Search){
$matches.ComputerName
}
}
答案 3 :(得分:0)
@ECHO Off
SETLOCAL
SET "namefound="
SET "convstatfullenc="
SET "protstatoff="
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q41141572.txt"
FOR /f "usebackqtokens=1,2*delims=: " %%a IN ("%filename1%") DO (
SET "lineprocessed="
IF /i "%%a"=="computer" IF /i "%%b"=="name" (
SET "namefound=%%c"
SET "convstatfullenc="
SET "protstatoff="
SET "lineprocessed=Y"
)
IF /i "%%a"=="protection" (
SET "protstatoff="
IF /i "%%b"=="status" IF /i "%%c"=="protection off" (
SET "protstatoff=Y"
SET "lineprocessed=Y"
)
)
IF /i "%%a"=="conversion" (
SET "convstatfullenc="
SET "protstatoff="
IF /i "%%b"=="status" IF /i "%%c"=="fully encrypted" (
SET "convstatfullenc=Y"
SET "lineprocessed=Y"
)
)
IF DEFINED lineprocessed IF DEFINED namefound IF DEFINED convstatfullenc IF DEFINED protstatoff (
CALL ECHO %%namefound%%
SET "lineprocessed="
)
IF NOT DEFINED lineprocessed (
SET "convstatfullenc="
SET "protstatoff="
)
)
GOTO :EOF
您需要更改sourcedir
的设置以适合您的具体情况。
我使用了一个名为q41141572.txt
的文件,其中包含我的测试数据。
仅处理第一个单词,如果单词为computer
和name
,则会分配一个新的namefound
,并标记两个标记convstatfullenc
和protstatoff
被清除并且标记为读取的行。因此,只要遇到新的computer name
,就会清除控制标志。
如果遇到conversion
,则清除控制标记,并且仅当行标记为已处理时,如果该行包含convstatfullenc
和status
,则仅设置fully encrypted
。
如果遇到protection
,则只有当该行还包含protstatoff
时才会设置status
,并且当该行再次被标记为处理时,protection off
将被设置。
如果已处理该行并且已设置每个标志,则表示已满足每个条件,因此显示存储的名称。清除lineprocessed
可确保在下一步清除两个控制标志。
因此,如果找到不是三个目标行的行,则该行未设置为已处理,因此将清除这两个控制标志。
如果找到conversion
行,则会清除protstatoff
并设置convstatfullenc
。
如果找到protection
行,则可以设置protstatoff
。
可以设置两个控件标志的唯一方法是protection
行直接位于conversion
行和之后通过全面测试。