电源外壳。修改 ascii 文本文件字符串,其中行号字符串已打开。交换机和 .NET 框架或 cmdlet 和管道?哪个更快?

2023-12-08

如何使用易于阅读且易于使用 PowerShell 5 添加/修改/删除的搜索字符串来修改 Windows ascii 文本文件中的字符串(LINE2“行号 LINE2 is on”)。此脚本将解析 2500 行文件,找到 139 个字符串实例,替换它们并覆盖原始字符串,平均耗时不到 165 毫秒,具体取决于您使用的方法。哪种方法更快?哪种方法更容易添加/修改/删除字符串?

搜索字符串“AROUND LINE {1-9999}”和“LINE2 {1-9999}”,并将 {1-9999} 替换为代码所在的{行号}。测试是使用 2500 行文件而不是两行sample.bat 完成的。

Sample.bat 包含两行:

ECHO AROUND LINE 5936
TITLE %TIME%   DISPLAY TCP-IP SETTINGS   LINE2 5937

方法一:使用 Get-Content + -replace + Set-Content:

Measure-command {
copy-item $env:temp\sample9.bat -d $env:temp\sample.bat -force
(gc $env:temp\sample.bat) | foreach -Begin {$lc = 1} -Process {
  $_ -replace 'AROUND LINE \d+', "AROUND LINE $lc" -replace 'LINE2 \d+', "LINE2 $lc"
  ++$lc
} | sc -Encoding Ascii $env:temp\sample.bat}

结果:十次运行为 175ms-387ms,平均为 215ms。

您可以通过添加/删除/修改 -replace 来修改搜索。

-replace 'AROUND LINE \d+', "AROUND LINE $lc" -replace 'LINE2 \d+', "LINE2 $lc" -replace 'PLACEMARK \d+', "PLACEMARK $lc"

powershell $env:temp\sample.ps1 $env:temp\sample.bat:

(gc $args[0]) | foreach -Begin {$lc = 1} -Process { $_ -replace 'AROUND LINE \d+', "AROUND LINE $lc" -replace 'LINE2 \d+', "LINE2 $lc" ++$lc } | sc -Encoding Ascii $args[0]

方法二:使用 switch 和 .NET 框架:

Measure-command {
    copy-item $env:temp\sample9.bat -d $env:temp\sample.bat -force
    $file = "$env:temp\sample.bat"
    $lc = 0
    $updatedLines = switch -Regex ([IO.File]::ReadAllLines($file)) {
      '^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$' { $Matches[1] + ++$lc + $Matches[2] }
      default { ++$lc; $_ }
    }
    [IO.File]::WriteAllLines($file, $updatedLines, [Text.Encoding]::ASCII)}

结果:十次运行 73ms-816ms,平均 175ms。

方法三:使用基于预编译正则表达式的 switch 和 .NET 框架优化版本:

Measure-command {
copy-item $env:temp\sample9.bat -d $env:temp\sample.bat -force
$file = "$env:temp\sample.bat"
$regex = [Regex]::new('^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$', 'Compiled, IgnoreCase, CultureInvariant')
$lc = 0
$updatedLines = & {foreach ($line in [IO.File]::ReadLines($file)) {
    $lc++
    $m = $regex.Match($line)
    if ($m.Success) {
        $g = $m.Groups
        $g[1].Value + $lc + $g[2].Value
    } else { $line }
}}
[IO.File]::WriteAllLines($file, $updatedLines, [Text.Encoding]::ASCII)}

结果:十次运行为 71ms-236ms,平均为 106ms。

添加/修改/删除您的搜索字符串:

AROUND LINE|LINE2|PLACEMARK
AROUND LINE|LINE3
LINE4

powershell $env:temp\sample.ps1 $env:temp\sample.bat:

$file=$args[0]
$regex = [Regex]::new('^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$', 'Compiled, IgnoreCase, CultureInvariant')
    $lc = 0
    $updatedLines = & {foreach ($line in [IO.File]::ReadLines($file
)) {
        $lc++
        $m = $regex.Match($line)
        if ($m.Success) {
            $g = $m.Groups
            $g[1].Value + $lc + $g[2].Value
        } else { $line }
    }}
    [IO.File]::WriteAllLines($file
, $updatedLines, [Text.Encoding]::ASCII)

Editor's note: This is a follow-up question to Iterate a backed up ascii text file, find all instances of {LINE2 1-9999} replace with {LINE2 "line number the code is on"}. Overwrite. Faster?

The evolution of this question from youngest to oldest: 1. 54757890 2. 54737787 3. 54712715 4. 54682186

Update: I've used @mklement0 regex solution.


switch -Regex -File $file {
  '^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$' { $Matches[1] + ++$lc + $Matches[2] }
  default { ++$lc; $_ }
}
  • 鉴于正则表达式^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$仅包含2捕获组 - 行的一部分before要替换的数字(\d+)和线的一部分after,您必须用索引引用这些组1 and 2进入自动的$Matches多变的在输出中(不是2 and 3).

    • 注意(?:...) is a 非捕获组,因此根据设计它不会反映在$Matches.
  • 而不是读取文件[IO.File]::ReadAllLines($file),我正在使用-File选项与switch,它直接从文件中读取行$file.

  • The ++$lc inside default { ++$lc; $_ }确保行计数器也增加不匹配线之前将手头的线穿过($_).


性能说明

  • 您可以通过以下方式稍微提高性能模糊的优化:

    # Enclose the switch statement in & { ... } to speed it up slightly.
    $updatedLines = & { switch -Regex -File ... }
    
  • 对于高迭代计数(大量行),使用预编译的[regex]实例而不是一个字符串字面量PowerShell 在幕后转换为正则表达式可以进一步加快速度 - 请参阅下面的基准测试。

  • 另外,如果出现这种情况——敏感的匹配就够了,可以挤掉a little通过添加更多性能-CaseSensitive的选项switch陈述。

  • 在高水平上,使解决方案变得快速的是使用switch -File处理线条,并且一般来说,使用 .NET 类型进行文件 I/O(而不是 cmdlet)(IO.File]::WriteAllLines()在这种情况下,如问题所示) - 另请参阅这个相关答案.

    • 也就是说,马斯泽的回答提供了高度优化的foreach基于预编译正则表达式的循环方法,速度更快更高的迭代次数- 然而,它更加冗长。

基准测试

  • 以下代码比较了该答案的性能switch与 marsze 的接近foreach方法。

  • 请注意,为了使两个解决方案完全等效,进行了以下调整:

    • The & { ... }优化已添加到switch命令也是如此。
    • The IgnoreCase and CultureInvariant选项已添加到foreach匹配选项 PS 正则表达式的方法隐含地 use.

不使用6行样本文件,而是分别使用600行、3000行和30000行文件进行性能测试,以显示迭代次数对性能的影响。

正在对 100 次运行进行平均。

结果示例从我运行 Windows PowerShell v5.1 的 Windows 10 计算机 -absolute时间并不重要,但希望relative性能显示在Factor栏目一般具有代表性:

VERBOSE: Averaging 100 runs with a 600-line file of size 0.03 MB...

Factor Secs (100-run avg.) Command
------ ------------------- -------
1.00   0.023               # switch -Regex -File with regex string literal...
1.16   0.027               # foreach with precompiled regex and [regex].Match...
1.23   0.028               # switch -Regex -File with precompiled regex...


VERBOSE: Averaging 100 runs with a 3000-line file of size 0.15 MB...

Factor Secs (100-run avg.) Command
------ ------------------- -------
1.00   0.063               # foreach with precompiled regex and [regex].Match...
1.11   0.070               # switch -Regex -File with precompiled regex...
1.15   0.073               # switch -Regex -File with regex string literal...


VERBOSE: Averaging 100 runs with a 30000-line file of size 1.47 MB...

Factor Secs (100-run avg.) Command
------ ------------------- -------
1.00   0.252               # foreach with precompiled regex and [regex].Match...
1.24   0.313               # switch -Regex -File with precompiled regex...
1.53   0.386               # switch -Regex -File with regex string literal...

注意在较低迭代次数下的情况switch -regex with a 字符串字面量最快,但大约 1,500 行foreach带有预编译的解决方案[regex]实例开始变得更快;使用预编译的[regex]实例与switch -regex回报程度较低,只是迭代次数较多。

基准代码, 使用Time-Command功能:

# Sample file content (6 lines)
$fileContent = @'
TITLE %TIME%   NO "%zmyapps1%\*.*" ARCHIVE ATTRIBUTE   LINE2 1243
TITLE %TIME%   DOC/SET YQJ8   LINE2 1887
SET ztitle=%TIME%: WINFOLD   LINE2 2557
TITLE %TIME%   _*.* IN WINFOLD   LINE2 2597
TITLE %TIME%   %%ZDATE1%% YQJ25   LINE2 3672
TITLE %TIME%   FINISHED. PRESS ANY KEY TO SHUTDOWN ... LINE2 4922

'@

# Determine the full path to a sample file.
# NOTE: Using the *full* path is a *must* when calling .NET methods, because
#       the latter generally don't see the same working dir. as PowerShell.
$file = "$PWD/test.bat"

# Note: input is the number of 6-line blocks to write to the sample file,
#       which amounts to 600 vs. 3,000 vs. 30,0000 lines.
100, 500, 5000 | % { 

  # Create the sample file with the sample content repeated N times.
  $repeatCount = $_ 
  [IO.File]::WriteAllText($file, $fileContent * $repeatCount)

  # Warm up the file cache and count the lines.
  $lineCount = [IO.File]::ReadAllLines($file).Count

  # Define the commands to compare as an array of scriptblocks.
  $commands =
    { # switch -Regex -File with regex string literal
      & { 
        $i = 0
        $updatedLines = switch -Regex -File $file {
          '^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$' { $Matches[1] + ++$i + $Matches[2] }
          default { ++$i; $_ }
        } 
        [IO.File]::WriteAllLines($file, $updatedLines, [text.encoding]::ASCII)
      }
    }, { # switch -Regex -File with precompiled regex
      & {
        $i = 0
        $regex = [Regex]::new('^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$', 'Compiled, IgnoreCase, CultureInvariant')
        $updatedLines = switch -Regex -File $file {
          $regex { $Matches[1] + ++$i + $Matches[2] }
          default { ++$i; $_ }
        } 
        [IO.File]::WriteAllLines($file, $updatedLines, [text.encoding]::ASCII)
      }
    }, { # foreach with precompiled regex and [regex].Match
      & {
        $regex = [Regex]::new('^(.*? (?:AROUND LINE|LINE2) )\d+(.*)$', 'Compiled, IgnoreCase, CultureInvariant')
        $i = 0
        $updatedLines = foreach ($line in [IO.File]::ReadLines($file)) {
            $i++
            $m = $regex.Match($line)
            if ($m.Success) {
                $g = $m.Groups
                $g[1].Value + $i + $g[2].Value
            } else { $line }
        }
        [IO.File]::WriteAllLines($file, $updatedLines, [Text.Encoding]::ASCII)    
      }
    }

  # How many runs to average.
  $runs = 100

  Write-Verbose -vb "Averaging $runs runs with a $lineCount-line file of size $('{0:N2} MB' -f ((Get-Item $file).Length / 1mb))..."

  Time-Command -Count $runs -ScriptBlock $commands | Out-Host

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

电源外壳。修改 ascii 文本文件字符串,其中行号字符串已打开。交换机和 .NET 框架或 cmdlet 和管道?哪个更快? 的相关文章

  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 检测 PowerShell 开关

    我正在用 C 开发 PowerShell cmdlet 并且有 true false switch 语句 我注意到 如果我希望 bool 为 true 我需要指定 SwitchName true 否则我会得到 Missing an argu
  • jQuery mousemove 性能 - 节流事件?

    我们面临着与 mousemove 连接的 jQuery 事件传播性能问题 我们有一个屏幕填充画布 需要跟踪用户是否在其上拖动鼠标 因此我们在该对象上添加了一个鼠标移动侦听器 如下所示 ourCanvas on mousemove funct
  • Powershell 新的 ScheduledTaskSettingsSet

    我尝试添加新的ScheduledTaskSettingsSet https technet microsoft com en us library jj649824 v wps 630 aspx具有自定义设置 根据 Technet 有可能的
  • 引用同一 PSCustomObject 的另一个属性

    我有一个PSCustomObject已声明并且它有多个成员 其中一些需要互相参考 例如 data PSCustomObject a x b y c z d a b c 我所期望的是 data d回来 x y z 我尝试通过以下方式引用其他属
  • 如何加速Python中的N维区间树?

    考虑以下问题 给定一组n间隔和一组m浮点数 对于每个浮点数 确定包含该浮点数的区间子集 这个问题已经通过构建一个解决区间树 https en wikipedia org wiki Interval tree 或称为范围树或线段树 已经针对一
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • Powershell:输出文件

    我正在尝试将所有控制台输出记录到文件中 移动项目 D scripts fileA D scripts fileB verbose Force 输出文件 D scripts move log 追加 如果该文件不存在 则正在创建该文件 但详细信
  • 在 Powershell 中,按记录类型拆分大型文本文件的最有效方法是什么?

    我正在使用 Powershell 进行一些 ETL 工作 读取压缩文本文件并根据每行的前三个字符将它们拆分出来 如果我只是过滤输入文件 我可以将过滤后的流传输到 Out File 并完成它 但我需要将输出重定向到多个目的地 据我所知 这不能
  • JavaScript 中的巨大字符串替换?

    我有一个小型 JavaScript 应用程序 可以解析用户放入浏览器中的文件 最近我发现一些非英语字符的问题 此处放置的文件类型使用 Windows 1252 字符集 因此诸如 实际上是通过 我必须将它们全部转换为正确的字符 例如 我得到S
  • PowerShell:如何强制以数组而不是对象的形式获取结果

    result Get ADUser Filter filter 如果我有 2 个或更多结果 则将 x 作为数组获取 但如果我只有一个结果 则将 x 作为对象获取 如何使其更正确 始终接收数组 空 包含一个元素或包含一些元素 Try x ge
  • 如果未提供值,如何从 cmdlet 中省略 powershell 参数?

    我正在尝试执行下面的 Powershell 命令 在交换服务器上创建一个新的地址列表 其中包含名称 容器等参数 Container是可选输入 参数 如果未提供其值 如何从 cmdlet 中省略它 我尝试过IF有条件但但似乎不起作用 这里有什
  • 在 Powershell 中使用用户名/密码连接到网络文件夹

    我经常在 Powershell 中访问共享网络文件夹以获取文件等 但如果共享需要用户名 密码 Powershell 不会提示我输入这些信息 这与 Windows 资源管理器不同 如果我首先在 Windows 资源管理器中连接到该文件夹 Po
  • 替换除引号内的逗号之外的逗号

    Date Time Ref Sen ATN Flow PCB temp Status Battery BC 2015 04 23 12 30 00 779581 908043 15 254 49 31 0 100 2015 04 23 12
  • 在Python中使用.replace替换多个字符[重复]

    这个问题在这里已经有答案了 所以我试图制作一个简单的程序 将一个短语解码为不同的短语 这是我现在的代码 def mRNA decode phrase newphrase phrase replace A U phrase replace T
  • 如何在读取文件期间从每一行中删除换行符? [复制]

    这个问题在这里已经有答案了 我正在从包含一个 字 行的文件中读取行 例如 dog cat person tree 每个单词还包含一个换行符 n特点 我想将它们读入列表并丢弃换行符 我设计的方法是阅读readlines 然后将列表处理为str
  • PowerShell 中的变量作用域

    PowerShell 的一个遗憾是函数和脚本块是动态作用域的 但另一件事让我感到惊讶的是 变量在内部作用域内表现为写时复制 array g function foo array h Write Host array array s Writ
  • SignalR 似乎正在减慢我的 MVC/Azure 应用程序的启动速度

    我有一个 MVC 应用程序在 Windows Azure 上的 WebRole 上的 NET 4 5 下运行 使用 SignalR 1 0 alpha2 并使用 ServiceBus 底板 在我的 App Start 文件夹中 我有 Reg
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • 如果 PyPy 快 6.3 倍,为什么我不应该使用 PyPy 而不是 CPython?

    我已经听到很多关于PyPy http en wikipedia org wiki PyPy项目 他们声称它比现有技术快 6 3 倍CPython http en wikipedia org wiki CPython口译员开启他们的网站 ht

随机推荐

  • 由于未注册 Windows.Launch 合同,Windows 10 分配的访问应用程序无法启动

    我有一个 WPF 应用程序 我已使用以下命令将其转换为 UWP 应用程序DesktopAppConverter为了运行它分配的访问权限模式 转换后的应用程序在非分配访问模式下运行时可以工作 可以安装并正常运行 但是 当我将其设置为分配的访问
  • 无法使用 cURL 将 SSH 密钥发送到 Github

    我正在尝试将我的公共 ssh 密钥发送到 Github 我将密钥设置为 shell 中的变量 但它给出了key is invalid You must supply a key in OpenSSH public key format错误
  • 在堆栈弹出中反应本机路由通量重新渲染组件

    如何重新运行 React 组件生命周期方法来确定在从堆栈转换回以前的屏幕时是否需要重新渲染React Native 路由器 Flux 设想 场景 A gt B gt A 假设 A 是初始场景 我们使用 a 从 A 导航到 B推即 Actio
  • 为什么我们先复制然后移动?

    我在某处看到代码 其中有人决定复制一个对象 然后将其移动到类的数据成员 这让我感到困惑 因为我认为移动的全部目的是为了避免复制 这是示例 struct S S std string str data std move str 这是我的问题
  • 带有列表和字典的嵌套循环

    所以我有点陷入了一个问题 本质上 我想使用列表和字典运行一个嵌套循环 但我似乎不知道如何操作 我的用例是运行一个 playbook 它将通过使用主体列表签署公钥来生成 SSH 证书 我有一个充当跳转主机的主机列表 称为 bastionHos
  • 如何获取java日历中每月第一个星期三的日期

    我如何使用java日历类获取该月下一个第一个星期三的日期 例如 Today 24 03 2012 the next first Wednesday will be 04 04 2012 On 05 04 2012 the next firs
  • 这个预提交钩子如何修复尾随空格?

    发生了什么事这个预提交钩子 我认为更改文件会导致它们被重新暂存 bin sh A git hook script to find and fix trailing whitespace in your commits Bypass it w
  • x86-64 分段错误保存堆栈指针

    我目前正在关注本教程 但我不是那所学校的学生 GDB 给我一个分段错误thread start在线上 movq rsp rdi save sp in old thread s tcb 当我回溯时 这是附加信息 0 thread start
  • 如何使用 JPA 映射 Duration 类型

    我在一个类型的类中有一个属性字段javax xml datatype Duration 它基本上代表一个时间跨度 例如 4 小时 34 分钟 JPA 告诉我这是一个无效类型 这并没有让我感到震惊 这有什么好的解决办法吗 我可以实现我自己的
  • 如何将输出写入 Android 中的日志?

    我想将一些调试输出写入日志以使用 logcat 进行查看 如果我向 System out 写入一些内容 则该内容已显示在 logcat 中 写入日志并向输出添加级别和标签的干净方法是什么 调查android util Log 它允许您写入具
  • 如何捕获 Flash 影片成功加载时的事件触发?

    我目前正在使用 jQuery 以及 swfObject 将 swf 影片动态嵌入到我的网页中 我目前在将 immem 的音乐播放器嵌入我的网页时遇到问题 因为他们的嵌入代码没有任何加载屏幕 因此 当我使用 swfObject 替换元素时 该
  • 从 res/raw 文件夹设置铃声

    我正在尝试在中设置音频文件 res raw 以编程方式将文件夹作为默认铃声 我有以下文件 如下所示 myapp res raw file mp3 我有以下代码 但不幸的是它完全无法设置铃声 我不确定是什么导致了这个问题 但想知道是否有人有任
  • django-admin.py:找不到命令(bluehost 服务器)

    经过6个多小时的挣扎 我决定寻求帮助 任务 在Django的帮助下创建一个项目工具 Windows Vista Putty SSH地点 Bluehost www bluehost com 服务器 我已经阅读过有关同一问题的这些主题 bash
  • TIME_WAIT 连接过多,出现“无法分配请求的地址”

    我有一个小型 Web 应用程序 它打开 TCP 套接字连接 发出命令 读取响应 然后关闭对特定 REST 端点的每个请求的连接 我已经开始使用 Apache JMeter 对端点进行负载测试 并注意到运行一段时间后 我开始看到诸如 无法分配
  • Laravel 4 - 无法检索一对多关系中的数据

    我有一个报价模型 class Quote extends Eloquent public function quote lines return this gt hasMany QuoteLine 还有一个 QuoteLine 模型 cla
  • 添加 Azure Ad Oauth2 JWT 令牌声明

    我只是想知道是否有办法通过 Azure 门户向 Azure Ad OAuth2 JWT 令牌添加或指定自定义声明 或者这是唯一可能的代码方面 据我所知 Azure AD目前不支持发出自定义声明 作为解决方法 我们可以使用 Azure AD
  • 通过名称获取 React 组件

    有没有办法通过名称访问 React 组件 例如 使用 React devtools 我可以搜索组件并使用以下命令访问控制台中最近选择的组件 r 有没有办法在没有 React 开发工具的情况下访问这些组件 IE 我可以使用查询来获取这些组件吗
  • 删除R中欧元符号后面的字符

    我有一个欧元符号保存在 欧元 变量中 euro lt u20AC euro 1 并且 eurosearch 变量包含 此 SOW 中定义的服务 价格为 15 896 80 欧元 如果从 执行 eurosearch 1 services as
  • 如何使用 iso_c_binding 声明指针的指针?

    我正在写一个iso c 绑定在 Fortran 中调用具有以下原型的 C 函数 int zmat run const size t inputsize unsigned char inputstr size t outputsize uns
  • 电源外壳。修改 ascii 文本文件字符串,其中行号字符串已打开。交换机和 .NET 框架或 cmdlet 和管道?哪个更快?

    如何使用易于阅读且易于使用 PowerShell 5 添加 修改 删除的搜索字符串来修改 Windows ascii 文本文件中的字符串 LINE2 行号 LINE2 is on 此脚本将解析 2500 行文件 找到 139 个字符串实例