PowerShell WinForms 文本框,防止不需要的正则表达式模式字符
PowerShell WinForms textbox, prevent unwanted regex pattern characters
在 PowerShell 中,我一直在尝试不同的方法从 WinForms 文本框中删除所有字符,而不是我需要的模式,但我无法为我所追求的找到更好的解决方案;我正在学习正则表达式,需要一些指导。这对我来说很基本,但我觉得我错过了一些明显的东西。我正在使用文本框的 TextChanged 事件来防止输入非法字符,并且我有一个(感觉上)臃肿的解决方案。
目标:
- 用户允许输入单个前导美元符号,后跟来自
[A-V0-9]
的最多 6 个字符
- 如果未键入
$
,则键入的第一个合法字符应生成前导 $
,后跟所述合法字符(键入 A
将生成 $A
文本框)
- 如果首先输入了非法字符,文本框中不应产生前导
$
- 非法字符不会出现在文本框中
- 粘贴的文本processed/stripped尽可能高效
- 删除的最后一个字符也会删除剩余的
$
- 如果文本框显示
$T
并且用户退格 T
留下一个 $
,剩余的 $
也将被删除
粘贴到文本框示例:
$$-#AZY$B9=%
会变成 $AB9
Z))%ABC$YD144%$
会变成 $ABCD14
$ZY%*#@!
在文本框中不产生任何内容
到目前为止我尝试过的事情:
- 使用
-split '^${1}'
和 -replace '[^A-V0-9]'
去除所有内容,然后将 $
添加回去
- 我真诚地道歉 - 我不记得这个解决方案出现了什么问题,但在某些情况下它的表现并不像我预期的那样
- 使用
ForEach
循环检查字符串中的每个字符并替换那些不匹配的字符 [A-V0-9]
然后插入 $
- 这是我目前使用的臃肿解决方案
- 使用屏蔽文本框,但屏蔽字符串不接受 范围 个字符
- 设置
$txtTextbox.MaxLength = 8
- 这会阻止正确处理粘贴的文本
- 使用 regex101.com、使用环顾四周等
进行了相当多的谷歌搜索和摆弄正则表达式
- 使用布尔标志来确定单个前导
$
是否首先被手动 typed/pasted 所以它不会在输入后立即被删除(但保留能力在删除最后一个合法字符时清除文本框是否使用 Backspace/Delete/CTRL+X 剪切等)
- 找到这个悖论的优雅解决方案正在逃避我(允许输入
$
但删除 $
如果它是文本框中唯一剩余的字符)
这是我目前在文本框的 TextChanged 事件中主要有效的解决方案:
Clear-Host
Add-Type -AssemblyName System.Windows.Forms
$btnExit = New-Object System.Windows.Forms.Button -Property @{
Location = '50, 100'
Text = 'E&xit'
}
$frmTestForm = New-Object System.Windows.Forms.Form -Property @{
CancelButton = $btnExit
FormBorderStyle = 'Fixed3D'
MaximizeBox = $false
}
$txtTextbox = New-Object System.Windows.Forms.TextBox -Property @{
Location = '50, 50'
CharacterCasing = 'Upper'
}
$frmTestForm.Controls.Add($btnExit)
$frmTestForm.Controls.Add($txtTextbox)
$txtTextbox.Add_TextChanged({
$TempString = $txtTextbox.Text
foreach ($Character in $txtTextbox.Text.ToCharArray() )
{
# Working, but doesn't allow user to type a '$'
if (! ([regex]::IsMatch($Character, '^[A-V0-9]$' ) ))
{
$TempString = $TempString.Replace([string]$Character, "")
}
}
if ($TempString.Length -ne 0 -and $TempString[0] -ne '$')
{
# Add a leading '$' if there isn't one
$txtTextbox.Text = '$' + $TempString.Substring(0, [System.Math]::Min(6, $TempString.Length))
}
elseif ($txtTextbox.Text -eq '$')
{
# Deletes the $ automatically once the last remaining (legal) character is deleted.
# This also unfortunately prevents the user from manually typing a leading '$'
$txtTextbox.Clear()
}
else
{
# Prevent leading illegal characters from showing up/producing '$' and nothing else
$txtTextbox.Text = ''
}
$txtTextbox.Select($txtTextbox.Text.Length, 0)
})
$btnExit.Add_Click({
$frmTestForm.Close()
})
$frmTestForm.Add_Shown({
$txtTextbox.Select()
})
[System.Windows.Forms.Application]::Run($frmTestForm)
它不允许用户手动输入 $
,如评论中所述,但如果允许这会引入更多膨胀,我可能愿意放弃。
归根结底,我的问题很简单:
正则表达式是否符合:
$txtTextbox.Text = $txtTextbox.Text -replace 'everything that isn't a leading $ in addition to [^A-V0-9]{0,6}'
与一次评估一个字符相比 simpler/faster/more 效率高吗?该正则表达式会是什么样子?
提前感谢您的任何见解或(希望是建设性的)批评。
-保罗
使用你的测试字符串,我想到了这个:
$txtTextbox.Add_TextChanged({
$TempString = $this.Text
if ($TempString -ne '$') {
$TempString = ($this.Text).TrimStart('$') -replace '[^A-V0-9]'
if ($TempString.Length -gt 6) { $this.Text = '[=10=]' -f $TempString.Substring(0,6) }
elseif ($TempString.Length) { $this.Text = '[=10=]' -f $TempString }
else { $this.Clear() }
}
elseif ($this.Tag -eq 2) {
# user backspaced the last character before the '$'
$this.Clear()
}
$this.Tag = $this.Text.Length # keep track of the current text length
$this.Select($this.Text.Length, 0) # set the cursor to the end
})
在 PowerShell 中,我一直在尝试不同的方法从 WinForms 文本框中删除所有字符,而不是我需要的模式,但我无法为我所追求的找到更好的解决方案;我正在学习正则表达式,需要一些指导。这对我来说很基本,但我觉得我错过了一些明显的东西。我正在使用文本框的 TextChanged 事件来防止输入非法字符,并且我有一个(感觉上)臃肿的解决方案。
目标:
- 用户允许输入单个前导美元符号,后跟来自
[A-V0-9]
的最多 6 个字符- 如果未键入
$
,则键入的第一个合法字符应生成前导$
,后跟所述合法字符(键入A
将生成$A
文本框) - 如果首先输入了非法字符,文本框中不应产生前导
$
- 如果未键入
- 非法字符不会出现在文本框中
- 粘贴的文本processed/stripped尽可能高效
- 删除的最后一个字符也会删除剩余的
$
- 如果文本框显示
$T
并且用户退格T
留下一个$
,剩余的$
也将被删除
- 如果文本框显示
粘贴到文本框示例:
$$-#AZY$B9=%
会变成$AB9
Z))%ABC$YD144%$
会变成$ABCD14
$ZY%*#@!
在文本框中不产生任何内容
到目前为止我尝试过的事情:
- 使用
-split '^${1}'
和-replace '[^A-V0-9]'
去除所有内容,然后将$
添加回去- 我真诚地道歉 - 我不记得这个解决方案出现了什么问题,但在某些情况下它的表现并不像我预期的那样
- 使用
ForEach
循环检查字符串中的每个字符并替换那些不匹配的字符[A-V0-9]
然后插入$
- 这是我目前使用的臃肿解决方案
- 使用屏蔽文本框,但屏蔽字符串不接受 范围 个字符
- 设置
$txtTextbox.MaxLength = 8
- 这会阻止正确处理粘贴的文本
- 使用 regex101.com、使用环顾四周等 进行了相当多的谷歌搜索和摆弄正则表达式
- 使用布尔标志来确定单个前导
$
是否首先被手动 typed/pasted 所以它不会在输入后立即被删除(但保留能力在删除最后一个合法字符时清除文本框是否使用 Backspace/Delete/CTRL+X 剪切等)- 找到这个悖论的优雅解决方案正在逃避我(允许输入
$
但删除$
如果它是文本框中唯一剩余的字符)
- 找到这个悖论的优雅解决方案正在逃避我(允许输入
这是我目前在文本框的 TextChanged 事件中主要有效的解决方案:
Clear-Host
Add-Type -AssemblyName System.Windows.Forms
$btnExit = New-Object System.Windows.Forms.Button -Property @{
Location = '50, 100'
Text = 'E&xit'
}
$frmTestForm = New-Object System.Windows.Forms.Form -Property @{
CancelButton = $btnExit
FormBorderStyle = 'Fixed3D'
MaximizeBox = $false
}
$txtTextbox = New-Object System.Windows.Forms.TextBox -Property @{
Location = '50, 50'
CharacterCasing = 'Upper'
}
$frmTestForm.Controls.Add($btnExit)
$frmTestForm.Controls.Add($txtTextbox)
$txtTextbox.Add_TextChanged({
$TempString = $txtTextbox.Text
foreach ($Character in $txtTextbox.Text.ToCharArray() )
{
# Working, but doesn't allow user to type a '$'
if (! ([regex]::IsMatch($Character, '^[A-V0-9]$' ) ))
{
$TempString = $TempString.Replace([string]$Character, "")
}
}
if ($TempString.Length -ne 0 -and $TempString[0] -ne '$')
{
# Add a leading '$' if there isn't one
$txtTextbox.Text = '$' + $TempString.Substring(0, [System.Math]::Min(6, $TempString.Length))
}
elseif ($txtTextbox.Text -eq '$')
{
# Deletes the $ automatically once the last remaining (legal) character is deleted.
# This also unfortunately prevents the user from manually typing a leading '$'
$txtTextbox.Clear()
}
else
{
# Prevent leading illegal characters from showing up/producing '$' and nothing else
$txtTextbox.Text = ''
}
$txtTextbox.Select($txtTextbox.Text.Length, 0)
})
$btnExit.Add_Click({
$frmTestForm.Close()
})
$frmTestForm.Add_Shown({
$txtTextbox.Select()
})
[System.Windows.Forms.Application]::Run($frmTestForm)
它不允许用户手动输入 $
,如评论中所述,但如果允许这会引入更多膨胀,我可能愿意放弃。
归根结底,我的问题很简单:
正则表达式是否符合:
$txtTextbox.Text = $txtTextbox.Text -replace 'everything that isn't a leading $ in addition to [^A-V0-9]{0,6}'
与一次评估一个字符相比 simpler/faster/more 效率高吗?该正则表达式会是什么样子?
提前感谢您的任何见解或(希望是建设性的)批评。
-保罗
使用你的测试字符串,我想到了这个:
$txtTextbox.Add_TextChanged({
$TempString = $this.Text
if ($TempString -ne '$') {
$TempString = ($this.Text).TrimStart('$') -replace '[^A-V0-9]'
if ($TempString.Length -gt 6) { $this.Text = '[=10=]' -f $TempString.Substring(0,6) }
elseif ($TempString.Length) { $this.Text = '[=10=]' -f $TempString }
else { $this.Clear() }
}
elseif ($this.Tag -eq 2) {
# user backspaced the last character before the '$'
$this.Clear()
}
$this.Tag = $this.Text.Length # keep track of the current text length
$this.Select($this.Text.Length, 0) # set the cursor to the end
})