regex - 仅过滤文件中的大写单词
问题描述
我有一个 output.txt 文件,其中包含大约 1000 个单词,如下所示:
每周会议 电影长篇 tblTrans_Ticket。 承认详情ALT2 MESSAGESTUB2ALT3 StartDayOfWeek 描述 MESSAGESTUB2ALT2 电影短片 应用 门票类型LONGALT
我需要过滤那个文件,只选择只有大写字符的单词,并去掉那些有小写字符的单词。
我在 PowerShell 中运行此命令:
Get-Content .\out.txt | ForEach-Object if ($_.IsUpper) {Write-Host $_}
并且外壳会一一解析所有单词,并且每个单词都会打印出我:
ForEach-Object :输入名称“if”无法解析为方法。 在行:1 字符:25 + ... 等内容 .\out.txt | ForEach-Object if ($_.IsUpper) {Write-Host $_} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (TAIL:PSObject) [ForEach-Object], PSArgumentException + FullyQualifiedErrorId : MethodNotFound,Microsoft.PowerShell.Commands.ForEachObjectCommand
我不明白我哪里错了?
解决方案
使用运算符对正则表达式(正则表达式-cmatch
)进行区分大小写的匹配:
Get-Content .\out.txt | Where-Object { $_ -cmatch '^\p{Lu}+$' }
-cmatch
-match
是运算符的区分大小写的变体(其别名是-imatch
);鉴于-match
不区分大小写,-cmatch
必须使用它来检测大小写区别。\p{Lu}
匹配单个大写字符 - 包括重音的非 ASCII 字符,例如Ü
[1] - 并+
在一行中添加一个或多个匹配项。将表达式括在^
(start of string) 和$
(end of string) 中意味着仅匹配完全由大写字符组成的行。- Ansgar Wiechers建议
-cnotmatch '\p{Ll}'
相反,它的工作方式略有不同:它将消除至少包含一个小写字符的行,这意味着即使它们(也)包含非字母字符(只要没有小写字母)也会保留这些行。
- Ansgar Wiechers建议
一个替代方案Select-String
可能会表现更好:
Select-String -CaseSensitive '^\p{Lu}+$' .\out.txt | Select-Object -ExpandProperty Line
Select-String
默认情况下也不区分大小写(通常与 PowerShell 一样),因此-CaseSensitive
此处需要切换。
请注意,尽管名称如此,Select-String
但从 PowerShell Core 6.1.0 开始,不支持直接输出匹配的行;相反,它输出匹配信息对象,其.Line
属性包含匹配的行,因此需要Select-Object -ExpandProperty Line
.
这个 GitHub issue建议添加一个新的 switch 参数来支持匹配字符串的直接输出。
至于你尝试了什么:
要由 cmdlet 执行的代码ForEach-Object
必须作为脚本块传递- 即,包含在{ ... }
.
您忽略了这样做,这导致了您看到的语法错误。
此外,[string]
类型(.NET 字符串)没有.IsUpper()
方法(即使有,您也忘记了()
after .IsUpper
)。
只有该[char]
类型有一个.IsUpper()
方法,即静态方法,您可以按如下方式调用它:[char]::IsUpper('A')
- 但您必须在循环中为输入字符串中的每个字符调用此方法:
Get-Content .\out.txt | Where-Object {
foreach ($c in $_.ToCharArray()) { if (-not [char]::IsUpper($c)) { return $False } }
$True
}
最后,不要使用Write-Host
返回结果-仅Write-Host
打印到控制台- 您将无法捕获或重定向此类输出[2]。相反,使用Write-Output
,或者更好的是,依赖 PowerShell 的隐式输出行为:简单地使用$_
它自己的语句将输出它 - 您既不捕获也不重定向的任何表达式或命令都会自动输出(发送到成功输出流)。
[1] 相比之下,使用字符范围表达式[A-Z]
只能识别 ASCII 范围(英文)大写字符。
[2] 在 PSv4- 中永远不会,但在 PSv5+ 中您可以通过额外的努力 - 但关键是这Write-Host
并不意味着输出结果(数据)。
推荐阅读
- c# - Asp.net Core 多文件上传到数据库
- c# - 安装程序自定义操作 - 注册 COM dll - C#
- java - 为什么类可以用泛型方法实现两个接口?
- c - 如果输出缓冲区有数据,调用 bufferevent_free 后会做什么?
- c# - C# 单个 UDP 侦听器,多个发送者提供数据问题
- javascript - 将 React 计时器重置为初始 const 值
- exception - 从 Asp.Net Web API 检索自定义异常到 Postman
- javascript - JavaScript 中未定义按键
- environment-modules - 设置环境模块
- python - (python):在每个点之后拆分成一个新行,并将每行的每个第一个字母大写,同时保留点