Reputation: 330
I want to pre-process C code, replacing
#include "../../abc/efg/hij.h"
with
"hij.h"
.
I use command
'#include "../../abc/efg/hij.h"' -replace '(#include\s+)(".*\w+\.h")',"$(Split-Path -Leaf `$2)"
To do the replacement. However, no matter how I tried (use single-/double- quote, $()
, and other methods), the final string (I did not Set-Content
yet, just want to see the result in standard output) is still "../../abc/efg/hij.h"
.
When I run Split-Path -Leaf "../../abc/efg/hij.h"
, the result is hij.h
, which is correct.
Can some one please tell me why this happens? Thank you very much!
Upvotes: 3
Views: 459
Reputation: 29033
Seems weird that you are doing path parsing with regex, but then trying to use Split-Path
to do it with a commandlet as well. Why not do the replace entirely with regexes?
Get rid of the bit you don't want by capturing it and replacing it with nothing:
PS C:\> '#include "../../abc/efg/hij.h"' -replace '(?<=#include\s+")(.*/)(?=\w+\.h")'
#include "hij.h"
or keep the bit you do want by capturing it and putting it into a new line:
PS C:\> '#include "../../abc/efg/hij.h"' -replace '#include\s+".*/(.*\.h)"','#include "$1"'
#include "hij.h"
Upvotes: 4
Reputation: 9266
The problem you are seeing is that the -replace
operator matches the regex and performs the replacement atomically. It provides no method to run any PowerShell code in between the two operations.
In your code, the scriptblock (Split-Path -Leaf $2)
evaluates first, before the regex has been matched. The result of that scriptblock ($null
, the empty string, or an exception depending on what value the variable $2
holds) is then passed to -replace
, with observed result.
What you want is to be able to run a PowerShell command in between matching the regex and replacing it. One way to do this is to use -match
to match the regular expression, and then build up your replacement string using the matches in the $matches
variable.
$oldLine -match '#include\s+"(.*\w+\.h)"'
$newLine = '#include "{0}"' -f (split-path -leaf $matches[1])
Optionally you can do the replacement using the -replace
operator, rather than building the whole line from scratch. However, because it evaluates the regex again, it can lead to performance problems for large input files.
Upvotes: 2