
You can just do a replacement on a decimal value list (default string conversion) where the values are bounded by spaces (word ends), e.g.: Set-Content "C:\NewFile.exe" -AsByteStream -Value $newByteArrayĪs far as I can oversee the quest, there is no need to do any hexadecimal conversion on a byte stream to do a replacement.
] $newByteArray = -split $byteString -replace '^', '0x' # Again, in *Windows PowerShell* use `-Encoding Byte` instead of `-AsByteStream`. # rather than via the pipeline, because that is much faster. # Note how the array is passed as an *argument*, via parameter -Value, # Convert the byte string back to a ] array, and save it to the # by spaces in the search and replacement strings. # Also note how the hex-digit sequences representing bytes are also separated # Note that since the string is guaranteed to be single-line, $byteString = $byteArray.ForEach('ToString', 'X') -join ' ' # *pairs* of hex digits, use 'X2' instead. # If you want to guaranteed that even byte values < 0x10 are represented as # where the whitespace-separated tokens are the hex. # Convert the byte array to a single-line "byte string", $byteArray = Get-Content C:\OldFile.exe -Raw -AsByteStream # `-Raw` ensures that the file is efficiently read as ] array at once. # In *Windows PowerShell*, replace `-AsByteStream` with `-Encoding Byte` # Read the entire file content as a ] array.
If prefer each byte to be consistently represented as two hex digits, even for values less than 0x10, (e.g., 01 rather than 1), use 'X2', which increases memory consumption, however.Īlso, you'll have to 0-prefix single-digit byte values in the search string too, e.g.:. ToString('X') on each array element and collecting the results. ForEach('ToString', 'X') is the equivalent of calling. representations created from byte-array input, use the same approach as for constructing the byte string from the input as shown below, e.g.: To construct the search and replacement strings as "byte strings" with space-separated hex. Here's an all-PowerShell solution (PSv4+) that doesn't require third-party functionality:Īs in your attempt, the entire file contents are read at once, and to-and- from string conversion is performed PSv4+ syntax Replacing byte sequences by search rather than fixed offsets: To address this ambiguity, the input "byte string" and the search string must be constructed differently: simply separate the digits constituting a byte each with spaces, as shown below. However, as iRon points out, while the above generically solves the replace-only-once problem, it is not a fully robust solution, because there is no guarantee that the search string will match at a byte boundary e.g., single-byte search string 12 would match the middle 12 in 0123, even though there is no byte 12 in the input string, composed of bytes 01 and 23. If your replacement string happens to contain $ characters that you want to be taken literally, $-escape them or, more generally, apply -replace '\$', '$$$$' (sic) to it. If your search string happens to contain regex metacharacters that you want to be taken literally, \-escape them individually or, more generally, pass the entire search term to ::Escape(). (See this answer for the more information about -replace and the syntax of the replacement operand.) (.*) captures all remaining characters in capture group 1, and $1 in the replacement string references them, which effectively removes just the first occurrence.
(?s)is an inline regex option that makes regex metacharacter. NET's String.Replace() method offer limiting replacing to one occurrence (or a fixed number).
Unfortunately, neither PowerShell's -replace operator nor. That said, it sounds like if you had a solution for replacing only the first occurrence of your search string, your original solution may work.įirst-occurrence-only string replacement: How can we specify an offset position into PowerShell to replace this sketchy -replace command.Īnsgar Wiechers' helpful answer addresses the offset question, and brianary's helpful answer shows a more PowerShell-idiomatic variant.