powershell字符串URL解码执行时间

powershell字符串URL解码执行时间,powershell,batch-file,cgi,Powershell,Batch File,Cgi,通过powershell oneliner在CGI混合脚本中执行URL解码: echo %C4%9B%C5%A1%C4%8D%C5%99%C5%BE%C3%BD%C3%A1%C3%AD%C3%A9%C5%AF%C3%BA| powershell.exe "Add-Type -AssemblyName System.Web;[System.Web.HttpUtility]::UrlDecode($Input) | Write-Host" 此oneliner在虚拟机上的执行时间

通过powershell oneliner在CGI混合脚本中执行URL解码:

echo %C4%9B%C5%A1%C4%8D%C5%99%C5%BE%C3%BD%C3%A1%C3%AD%C3%A9%C5%AF%C3%BA| powershell.exe "Add-Type -AssemblyName System.Web;[System.Web.HttpUtility]::UrlDecode($Input) | Write-Host"

此oneliner在虚拟机上的执行时间介于2-3秒之间。是否因为使用了.NET对象?有没有办法缩短执行时间?还有一些C编写的、速度极快的urldecode.exe实用程序,但不幸的是,它不吃STDIN。

如果您将输入数据作为字符串文本传递,请注意,如问题中的示例调用(而不是命令的输出):

  • 如果您是从交互式
    cmd.exe
    会话调用,
    %C4%9B%C5%A1%C4%8D%C5%99%C5%BE%C3%BD%C3%A1%C3%AD%C3%A9%C5%AF%C3%BA
    实例之间的任何令牌恰好是现有环境变量的名称(这似乎不太可能)

  • 从批处理文件中,必须转义
    %
    字符。将它们加倍——见;可通过对原始字符串应用以下PowerShell操作来获得:

    '%C4%9B%C5%A1%C4%8D%C5%99%C5%BE%C3%BD%C3%A1%C3%AD%C3%A9%C5%AF%C3%BA' -replace '%', '%%'
    

是否因为使用了.NET对象

  • 是的,
    powershell.exe
    ,作为基于.NET的应用程序,需要启动后者的运行时(CLR),这在性能方面是不平凡的

  • 此外,默认情况下,
    powershell.exe
    加载其
    $PROFILE
    变量中列出的初始化文件,这可能需要额外的时间

    • 传递
      -NoProfile
      CLI选项以抑制该选项

也有一些C编写的,闪电般的
urldecode.exe
实用程序,但不幸的是它不吃STDIN

如果是,如果可行,将数据作为参数传递;e、 g:

urldecode.exe "%C4%9B%C5%A1%C4%8D%C5%99%C5%BE%C3%BD%C3%A1%C3%AD%C3%A9%C5%AF%C3%BA"
如果数据来自另一个命令的输出,则可以使用
for/f
首先捕获变量,然后传递后者


如果确实需要调用powershell.exe,那么powershell的:

在优化性能方面,您可以做的不多:

  • 根据建议添加
    -NoProfile
  • 将输入数据作为参数传递
  • 避免不必要的调用,例如,并改用PowerShell的隐式输出行为。[1]

[1] 可选阅读:如何从PowerShell调用输出机器可解析数据? 注意:假设示例命令在PowerShell外部从
cmd.exe
/运行

  • PowerShell的CLI仅支持文本作为输出,不支持原始字节数据

  • 为了输出数据以供以后的编程处理,您可能必须明确确保输出的内容是机器可解析的,而不是仅用于显示的内容

有两个基本选择:

  • 依靠PowerShell的默认输出格式来输出开始时的字符串(文本),以及数字——但对于分数和非常大或很小的非整数,可能需要额外的工作

  • 明确使用结构化、基于文本的数据格式,如CSV或Json,来表示复杂对象


依赖PowerShell的默认输出格式:

  • 如果输出数据本身是文本(字符串),则无需额外努力。这适用于您的情况,因此只需隐式输出从
    [System.Web.HttpUtility]::UrlDecode()
    调用返回的字符串即可:

    # A simple example that outputs a 512-character string; note that 
    # printing to the _console_ (terminal) will insert line breaks for 
    # *display*, but the string data itself does _not_ contain any 
    # (other than a single _trailing one), irrespective of the 
    # console window width:
    powershell -noprofile -c "'x' * 512"
    
  • 如果输出数据包含数字,如果代码必须使用不同的有效区域性运行,则可能必须应用显式的区域性不变格式:

    • 真正的整数类型不需要特殊处理,因为它们的字符串表示形式实际上与区域性无关

    • 但是,小数(
      [double]
      [decimal]
      )确实使用了当前区域性的小数标记,这在以后的处理中可能不会出现:

      # With, say, culture fr-FR (French) in effect, this outputs
      # "1,2", i.e. uses a *comma* as the decimal mark.
      powershell -noprofile -c "1.2"
      
      # Simple workaround: Let PowerShell *stringify* the number explicitly
      # in an *expandable* (interpolating) string, which uses
      # the *invariant culture* for formatting, where the decimal
      # mark is *always "." (dot).
      # The following outputs "1.2", irrespective of what culture is in effect.    
      powershell -noprofile -c " $num=1.2; \"$num\" "
      
    • 最后,非常大和非常小的
      [double]
      值可能导致输出指数表示法(例如
      0.00000051的
      5.1E-07
      );要避免这种情况,需要使用,可以通过
      .ToString()
      方法执行:

      # The following outputs 0.000051" in all cultures, as intended.
      powershell -noprofile -c "$n=0.000051; $n.ToString('F6', [cultureinfo]::InvariantCulture)"
      
  • 如果您想以机器可解析的形式输出复杂对象的表示,需要做更多的工作,如下一节所述

    • 在这种情况下,依赖PowerShell的默认输出格式不是一个选项,因为隐式输出和(等效的显式调用)会导致CLI应用仅显示格式,这对人工观察者很有意义,但无法可靠地进行分析

    • 请注意,的使用不是一种替代方法
      写主机
      基本上不是为数据输出而设计的,它为复杂对象创建的文本表示通常对人类观察者来说甚至没有意义-有关更多信息,请参阅


使用结构化、基于文本的数据格式,如CSV或Json:

注:

  • 假设,最简单的方法是使用CLI的
    -OutputFormat Xml
    选项,该选项使用PowerShell本身用于远程处理和后台作业的基于Xml的CLIXML格式序列化输出-请参阅

  • 但是,这种格式只能由PowerShell本身在本机上理解,第三方应用程序必须基于.NET并使用

    • 此外,如果使用指定为脚本块的命令从PowerShell调用另一个PowerShell实例(
      {…}
      ),此格式将自动用于序列化和反序列化-请参阅。但是,很少需要调用PowerShell CLI fr
      # The following outputs 0.000051" in all cultures, as intended.
      powershell -noprofile -c "$n=0.000051; $n.ToString('F6', [cultureinfo]::InvariantCulture)"
      
      # Produces output helpful to the *human observer*, but isn't
      # designed for *parsing*.
      # `Get-ChildItem` outputs [System.IO.FileSystemInfo] objects.
      powershell -noprofile -c "Get-ChildItem /"
      
      C:\>powershell -noprofile -c "Get-Item $PSHOME | ConvertTo-Csv -NoTypeInformation"
      "PSPath","PSParentPath","PSChildName","PSDrive","PSProvider","PSIsContainer","Mode","BaseName","Target","LinkType","Name","FullName","Parent","Exists","Root","Extension","CreationTime","CreationTimeUtc","LastAccessTime","LastAccessTimeUtc","LastWriteTime","LastWriteTimeUtc","Attributes"
      "Microsoft.PowerShell.Core\FileSystem::C:\Windows\System32\WindowsPowerShell\v1.0","Microsoft.PowerShell.Core\FileSystem::C:\Windows\System32\WindowsPowerShell","v1.0","C","Microsoft.PowerShell.Core\FileSystem","True","d-----","v1.0","System.Collections.Generic.List`1[System.String]",,"v1.0","C:\Windows\System32\WindowsPowerShell\v1.0","WindowsPowerShell","True","C:\",".0","12/7/2019 4:14:52 AM","12/7/2019 9:14:52 AM","3/14/2021 10:33:10 AM","3/14/2021 2:33:10 PM","11/6/2020 3:52:41 AM","11/6/2020 8:52:41 AM","Directory"
      
      C:\>powershell -noprofile -c "Get-Item $PSHOME | ConvertTo-Json -Depth 1"
      {
          "Name":  "v1.0",
          "FullName":  "C:\\Windows\\System32\\WindowsPowerShell\\v1.0",
          "Parent":  {
                         "Name":  "WindowsPowerShell",
                         "FullName":  "C:\\Windows\\System32\\WindowsPowerShell",
                         "Parent":  "System32",
                         "Exists":  true,
                         "Root":  "C:\\",
                         "Extension":  "",
                         "CreationTime":  "\/Date(1575710092565)\/",
                         "CreationTimeUtc":  "\/Date(1575710092565)\/",
                         "LastAccessTime":  "\/Date(1615733476841)\/",
                         "LastAccessTimeUtc":  "\/Date(1615733476841)\/",
                         "LastWriteTime":  "\/Date(1575710092565)\/",
                         "LastWriteTimeUtc":  "\/Date(1575710092565)\/",
                         "Attributes":  16
                     },
          "Exists":  true
          // ...
      }