检查文件的前n个字节是否在PowerShell中是特定的

km0tfn4u  于 12个月前  发布在  Shell
关注(0)|答案(4)|浏览(152)

如何将文件中的字节与值的文字数组进行比较?

$path = "C:\BinaryFile.bin"
$bytes = Get-Content -LiteralPath $path -Encoding byte -TotalCount 4 -ReadCount 4
if ($bytes -eq [0 1 2 3]) { # How to compare to expected bytes?
    Write-Output "OK: $bytes"
}

字符串

lb3vh1jj

lb3vh1jj1#

可能是比较对象。没有输出意味着相等。同步窗口0表示精确顺序。

$path = 'file'
[byte[]](0..3) | set-content $path -Encoding Byte
$bytes = Get-Content $path -Encoding byte -TotalCount 4
if (! (compare-object $bytes 0,1,2,3 -syncwindow 0)) { 
    "OK: $bytes"
}

字符串
或者做一个字符串比较:

if ("0 1 2 3" -eq $bytes) {
    "OK: $bytes"
}

tyu7yeag

tyu7yeag2#

PowerShell没有内置的序列相等运算符,但您可以编写适合此目的的小实用程序函数:

function Test-ArrayEquals
{
    param([array]$ReferenceArray, [array]$DifferenceArray)

    if($ReferenceArray.Length -ne $DifferenceArray.Length){
        # not same length, not equal
        return $false
    }

    for($i = 0; $i -lt $ReferenceArray.Length; $i++){
        if($ReferenceArray[$i] -ne $DifferenceArray[$i]){
            # two aligned array members were found to not be equal
            return $false
        }
    }

    # we reached the end, array values must be equal
    return $true
}

字符串
现在您可以:

if (Test-ArrayEquals -ReferenceArray @(0, 1, 2, 3) -DifferenceArray $bytes) {
    # looks good!
}

uxh89sit

uxh89sit3#

其他答案提供了有用的解决方案,可以使用 any 类型的数组。
这里有一个适用于您的情况的快捷方式,它将数组 * 作为字符串 * 进行比较,利用PowerShell stringifies 数组的方式(请参阅下面的限制**):

if ("$bytes" -eq '1 2 3' ) { # Be sure to use *decimal* values
    Write-Output "OK: $bytes"
}

字符串

限制

PowerShell通过将数组的(字符串化的)元素与空格连接起来来串化数组;例如,$bytes = 0x1, 0x2, 0xA; "$bytes"成为一个具有逐字值1 2 10的字符串(注意如何使用数字的 decimal 表示)。
因此,通过它们的(PowerShell)字符串表示比较数组只有在满足以下条件的情况下才能 * 鲁棒地 * 工作:

  • 元素具有明确的字符串表示(通常是:.NET基元类型,如数字和字符串)
  • 没有元素的字符串表示有 embedded 空格。

如果元素是 * 字符串 *,并且您希望区分大小写 * 比较它们,请使用-ceq代替-eq

LINQ解决方案

此解决方案基于System.Linq.Enumerable.SequenceEqual(),适用于所有类型。
注意需要[byte[]]强制转换--它创建输入数组的强类型 * 副本 *(它们本身是[object[]]类型的)--以便方法调用工作:

if ([Linq.Enumerable]::SequenceEqual([byte[]] $bytes, [byte[]] (1, 2, 3))) {
    Write-Output "OK: $bytes"
}

  • 注意事项 *:在这种情况下,这并不重要,但总的来说,值得注意的是,这个方法在逐元素比较方面比Compare-Object-eq运算符执行的PowerShell相等测试更严格:值得注意的是,默认情况下,字符串元素比较时区分大小写。如果您选择[object[]]作为上述类型转换-以避免创建 * 副本 * 具有相同值的数字只有在它们的类型完全相同时才被认为是相等的;值得注意的是,数组字面量1, 2, 3创建了一个具有[int]值的[object[]]数组,而不是[byte]值。

从好的方面来说,LINQ的使用有可能比Compare-Object解决方案执行得更好-有关更多信息,请参阅this answer的底部部分。

6rqinv9w

6rqinv9w4#

数组可以通过Compare-Object进行比较。它读取文件的前四(4)个字节,并将其与文字数组进行比较。
在Windows PowerShell 5.1中:

Compare-Object `
    -ReferenceObject (Get-Content -Path '.\file.txt' -Encoding Byte -TotalCount 4) `
    -DifferenceObject @(97,100,115,102) -SyncWindow 0

字符串
在PowerShell Core 6.x+中:

Compare-Object `
    -ReferenceObject (Get-Content -Path '.\file.txt' -AsByteStream -TotalCount 4) `
    -DifferenceObject @(97,100,115,102) -SyncWindow 0


范例:

# Get-Content -Path .\firstfour.txt
adsf is the first four (4) bytes
dec 97,100,115,102
hex 61,64,73,66

# Format-Hex -Path .\firstfour.txt

   Label: C:\src\ttt\firstfour.txt

          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 61 64 73 66 20 69 73 20 74 68 65 20 66 69 72 73 adsf is the firs
0000000000000010 74 20 66 6F 75 72 20 28 34 29 20 62 79 74 65 73 t four (4) bytes
0000000000000020 0D 0A 64 65 63 20 39 37 2C 31 30 30 2C 31 31 35 ��dec 97,100,115
0000000000000030 2C 31 30 32 0D 0A 68 65 78 20 36 31 2C 36 34 2C ,102��hex 61,64,
0000000000000040 37 33 2C 36 36                                  73,66

# Compare-Object `
     -ReferenceObject (Get-Content -Path '.\firstfour.txt' -AsByteStream -TotalCount 4) `
     -DifferenceObject @(97,100,115,102) -SyncWindow 0

# $null -eq (Compare-Object `
     -ReferenceObject (Get-Content -Path '.\firstfour.txt' -AsByteStream -TotalCount 4) `
     -DifferenceObject @(97,100,115,102) -SyncWindow 0)

True

# Get-Content -Path .\w.txt

line1
line2
line3
line4

# Format-Hex -Path .\w.txt

   Label: C:\src\ttt\w.txt

          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 6C 69 6E 65 31 0D 0A 6C 69 6E 65 32 0D 0A 6C 69 line1��line2��li
0000000000000010 6E 65 33 0D 0A 6C 69 6E 65 34 0D 0A             ne3��line4��

# Compare-Object `
     -ReferenceObject (Get-Content -Path '.\w.txt' -AsByteStream -TotalCount 4) `
     -DifferenceObject @(97,100,115,102) -SyncWindow 0

InputObject SideIndicator
----------- -------------
         97 =>
        108 <=
        100 =>
        105 <=
        115 =>
        110 <=
        102 =>
        101 <=

# $null -eq (Compare-Object `
     -ReferenceObject (Get-Content -Path '.\w.txt' -AsByteStream -TotalCount 4) `
     -DifferenceObject @(97,100,115,102) -SyncWindow 0)

False

相关问题