Skip to content

Commit 8eb40c9

Browse files
StartAutomatingStartAutomating
authored andcommitted
Adding Search-PipeScript (#114)
1 parent 475f283 commit 8eb40c9

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed

Search-PipeScript.ps1

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
function Search-PipeScript {
2+
<#
3+
.Synopsis
4+
Searches PowerShell and PipeScript ScriptBlocks
5+
.Description
6+
Searches PowerShell and PipeScript ScriptBlocks, files, and text
7+
.Example
8+
Search-PipeScript -ScriptBlock {
9+
$a
10+
$b
11+
$c
12+
"text"
13+
} -AstType Variable
14+
.LINK
15+
Update-PipeScript
16+
#>
17+
[OutputType('Search.PipeScript.Result')]
18+
[Alias('Search-ScriptBlock')]
19+
param(
20+
# The ScriptBlock that will be searched.
21+
[Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]
22+
[Alias('ScriptBlock','Text')]
23+
[ValidateScript({
24+
$validTypeList = [System.String],[System.Management.Automation.ScriptBlock],[System.IO.FileInfo]
25+
$thisType = $_.GetType()
26+
$IsTypeOk =
27+
$(@( foreach ($validType in $validTypeList) {
28+
if ($_ -as $validType) {
29+
$true;break
30+
}
31+
}))
32+
if (-not $isTypeOk) {
33+
throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','scriptblock','System.IO.FileInfo'."
34+
}
35+
return $true
36+
})]
37+
38+
$InputObject,
39+
# The AST Condition.
40+
# These Script Blocks
41+
[Parameter(ValueFromPipelineByPropertyName)]
42+
[Alias('ASTDelegate')]
43+
[ScriptBlock[]]
44+
$AstCondition,
45+
# A shortname for the abstract syntax tree types.
46+
[Parameter(ValueFromPipelineByPropertyName)]
47+
[ValidateScript({
48+
$validTypeList = [System.String],[System.Text.RegularExpressions.Regex],[System.String[]],[System.Text.RegularExpressions.Regex[]]
49+
$thisType = $_.GetType()
50+
$IsTypeOk =
51+
$(@( foreach ($validType in $validTypeList) {
52+
if ($_ -as $validType) {
53+
$true;break
54+
}
55+
}))
56+
if (-not $isTypeOk) {
57+
throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','regex','string[]','regex[]'."
58+
}
59+
return $true
60+
})]
61+
62+
$AstType,
63+
64+
# One or more regular expressions to match.
65+
[Parameter(ValueFromPipelineByPropertyName)]
66+
[Alias('RegEx')]
67+
[ValidateScript({
68+
$validTypeList = [System.String],[System.Text.RegularExpressions.Regex],[System.String[]],[System.Text.RegularExpressions.Regex[]]
69+
$thisType = $_.GetType()
70+
$IsTypeOk =
71+
$(@( foreach ($validType in $validTypeList) {
72+
if ($_ -as $validType) {
73+
$true;break
74+
}
75+
}))
76+
if (-not $isTypeOk) {
77+
throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','regex','string[]','regex[]'."
78+
}
79+
return $true
80+
})]
81+
82+
$RegularExpression
83+
)
84+
process {
85+
$ScriptBlock = $null
86+
$Text = $null
87+
# If the input was a file
88+
if ($InputObject -is [IO.FileInfo]) {
89+
$inputCommand = # get the resolved command
90+
$ExecutionContext.SessionState.InvokeCommand.GetCommand(
91+
$InputObject.Fullname, 'ExternalScript,Application')
92+
# If the command was an external script
93+
if ($inputCommand -is [Management.Automation.ExternalScriptInfo]) {
94+
# Use it's ScriptBlock
95+
$ScriptBlock = $inputCommand.ScriptBlock
96+
}
97+
# If the command was an application, and it looks like PipeScript
98+
elseif (
99+
$inputCommand -is [Management.Automation.ApplicationInfo] -and
100+
$inputCommand.Source -match '\.ps$'
101+
) {
102+
# Load the file text
103+
$text = [IO.File]::ReadAllText($inputCommand.Source)
104+
# and create a script block.
105+
$scriptBlock = [ScriptBlock]::Create($text)
106+
}
107+
# Otherwise
108+
else
109+
{
110+
# Read the file contents as text.
111+
$text = [IO.File]::ReadAllText($inputCommand.Source)
112+
}
113+
}
114+
# If the inputObject was a [ScriptBlock]
115+
if ($InputObject -is [scriptblock]) {
116+
$scriptBlock = $InputObject # set $ScriptBlock
117+
}
118+
# If the InputObject is a string
119+
if ($InputObject -is [string]) {
120+
$Text = $InputObject # set $Text.
121+
}
122+
# If we have a ScriptBlock
123+
if ($scriptBlock) {
124+
# Reset $text to the ScriptBlock contents.
125+
$Text = "$scriptBlock"
126+
# If we have an ASTType to find
127+
if ($AstType) {
128+
foreach ($astTypeName in $AstType) {
129+
# See if it's a real type
130+
$realAstType =
131+
foreach ($potentialType in $AstType,
132+
"Management.Automation.Language.$AstType",
133+
"Management.Automation.Language.${AstType}AST"
134+
) {
135+
if ($potentialType -as [type]) {
136+
$potentialType -as [type]; break
137+
}
138+
}
139+
140+
# If it was a real type, but in the wrong namespace
141+
if ($realAstType -and $realAstType.Namespace -eq 'Management.Automation.Language') {
142+
Write-Error "'$astType' is not an AST type" # error and continue.
143+
continue
144+
}
145+
# Set the search condition
146+
$condition =
147+
if ($realAstType) {
148+
# If there was a real type, search for it.
149+
[ScriptBlock]::Create('param($ast) $ast -is [' + $realAstType.FullName + ']')
150+
}
151+
elseif ($astType -is [Regex]) {
152+
[scriptblock]::Create((
153+
'param($ast)
154+
$ast.GetType().Name -match ([Regex]::New(' +
155+
$astType.ToString().Replace("'", "''") + "','" +
156+
$astType.Options + "','" +
157+
$(if ($AstType.MatchTimeout -lt 0) {
158+
'00:00:05'
159+
} else {
160+
$AstType.MatchTimeout.ToString()
161+
}) + '))'
162+
))
163+
}
164+
elseif ($astType -as [regex]) {
165+
[ScriptBlock]::Create('param($ast) $ast.GetType().Name -match ' + $astType +'')
166+
} else {
167+
[ScriptBlock]::Create('param($ast) $ast.GetType().Name -like "*' + $astType +'*"')
168+
}
169+
170+
$AstCondition += $condition
171+
}
172+
}
173+
if ($AstCondition) {
174+
foreach ($condition in $AstCondition) {
175+
$ScriptBlock.Ast.FindAll($condition, $true) |
176+
& { process {
177+
$in = $this = $_
178+
[PSCustomObject][Ordered]@{
179+
'InputObject' =
180+
$inputObject
181+
'Result' =
182+
& {
183+
$_
184+
}
185+
'Expression' =
186+
$condition
187+
'ScriptBlock' =
188+
& {
189+
$ScriptBlock
190+
}
191+
'PSTypeName' =
192+
"Search.PipeScript.Result"
193+
}
194+
} }
195+
}
196+
}
197+
}
198+
if ($text) {
199+
if ($RegularExpression) {
200+
foreach ($regex in $RegularExpression) {
201+
$realRegex =
202+
if ($regex -is [regex]) {
203+
$regex
204+
} else {
205+
[Regex]::new($regex)
206+
}
207+
208+
$realRegex.Matches($text) |
209+
& { process {
210+
$in = $this = $_
211+
[PSCustomObject][Ordered]@{
212+
'InputObject' =
213+
$InputObject
214+
'Result' =
215+
& {
216+
$_
217+
}
218+
'Expression' =
219+
$realRegex
220+
'RegularExpression' =
221+
& {
222+
$realRegex
223+
}
224+
'PSTypeName' =
225+
"Search.PipeScript.Result"
226+
}
227+
} }
228+
}
229+
}
230+
}
231+
}
232+
}
233+
234+

0 commit comments

Comments
 (0)