【问题标题】:Regex to match only words without _ or -正则表达式仅匹配没有 _ 或 - 的单词
【发布时间】:2015-01-28 03:31:35
【问题描述】:

我正在尝试从每行仅包含一个单词的文本文件中提取单词。但我只想匹配单词中没有“_”(下划线)或“-”(破折号)的单词:
文件可能如下所示:

我只想提取第 1 行和第 2 行而忽略第 3 行和第 4 行 (即,当正则表达式匹配每一行时的结果应该是:

someword
SomeOtherword

每行没有“

我正在处理一个接近 100000 行的文件。我不想遍历每一行,因为需要处理时间非常快。我正在使用的代码:

$rx = '[\w-]+'
获取内容 $filename |选择字符串-模式 $rx -AllMatches |选择 -ExpandProperty 匹配 |选择 -ExpandProperty 值 |输出文件 $outputfile

【问题讨论】:

  • 我需要通过正则表达式完成此操作,因为我无法遍历我正在处理的文件的内容接近 100000 行并且需要快速处理。 $rx = "^[a-zA-Z]+$" 获取内容 $ofile |选择字符串-模式 $rx -AllMatches |选择 -ExpandProperty 匹配 | select -ExpandProperty Value
    "^[a-zA-Z]+$" 不匹配..
  • “我不想遍历每一行”是什么意思?您还打算如何检查每行是否有破折号或下划线?我使用我的答案在 4 秒内处理了一个 100k 行(~6MB)的文件。这还不够快吗?

标签: regex powershell


【解决方案1】:

如果您对性能敏感,这种方法明显更快(2.6 秒对 80 毫秒):

(Select-String '^[a-zA-Z]+$' file.txt -AllMatches).Matches.Value

这确实需要 PowerShell v3 的新功能。你没有说你使用的是哪个版本。

【讨论】:

  • 你确定这些时间?我尝试将结果写入文件(只是接受了我的答案并在管道末端粘贴了add-content)并得到了更像 11s 与 7s 的结果。可衡量,但不是 30 倍的差异。
  • 是的。 (measure-command {(Select-String '^[a-zA-Z]+$' file.txt -AllMatches).Matches.Value}).TotalSeconds 吐出 0.0857457 和 (measure-command {gc 'file.txt' | where { $_ -notmatch '-|_' } | foreach { $_.Trim('<', ' ') }}).TotalSeconds 在我的 HP Z420 上吐出 2.8649068,在 SSD 上运行 Windows 8.1。
  • 是的,我有类似的设置(SSD 上的 Windows 8.1)。我在我的文件上运行了几个不同的正则表达式,我认为这个真正闪耀的地方是当你只想要文件中的几行时。也就是说,性能提升主要是由于将字符串排除在管道之外。我的第一个测试匹配文件中的大部分行,因此差异较小。使用限制性更强的过滤器(仅从 100k 中提取几十行)显示出 3.7 秒与 200 毫秒的差异。
  • 谢谢。这解决了我的问题。很抱歉对处理如此迂腐。我的脚本做了很多其他处理器密集型的东西,这些东西加起来就是运行脚本所需的总时间。所以我试图将每个子进程保持在最小的延迟。
【解决方案2】:

要在 powershell 中进行正则表达式匹配,您可以使用 -match 运算符或 select-string。还有一个-notmatch 运算符和一个-NotMatch 标志select-string。两者都过滤缺少匹配项。

所以一种选择是

gc 'file.txt' | where { $_ -notmatch '-|_' } | foreach { $_.Trim('<', ' ') }

另一个是

gc 'file.txt' | select-string -NotMatch '-|_' | foreach { $_.Line.Trim('<', ' ') }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    相关资源
    最近更新 更多