PowerShell,在其他区域性中格式化值

PowerShell,在其他区域性中格式化值,powershell,locale,number-formatting,Powershell,Locale,Number Formatting,在PowerShell中是否有一种简单的方法可以在另一个区域设置中格式化数字等?我目前正在编写一些函数来简化SVG的生成,SVG使用作为十进制分隔符,而PowerShell在将浮点数转换为字符串时尊重我的区域设置(de) 有没有一种简单的方法可以为一个函数设置另一个区域设置而不卡住 .ToString((New-Object Globalization.CultureInfo "")) 在每个double变量之后 注意:这是关于用于格式化的区域设置,而不是格式字符串 (附带问题:在这种情况下,

在PowerShell中是否有一种简单的方法可以在另一个区域设置中格式化数字等?我目前正在编写一些函数来简化SVG的生成,SVG使用
作为十进制分隔符,而PowerShell在将浮点数转换为字符串时尊重我的区域设置(
de

有没有一种简单的方法可以为一个函数设置另一个区域设置而不卡住

.ToString((New-Object Globalization.CultureInfo ""))
在每个
double
变量之后

注意:这是关于用于格式化的区域设置,而不是格式字符串

(附带问题:在这种情况下,我应该使用不变文化还是更确切地说
en-US
?)

预计到达时间:嗯,我在这里尝试的是如下内容:

function New-SvgWave([int]$HalfWaves, [double]$Amplitude, [switch]$Upwards) {
    "<path d='M0,0q0.5,{0} 1,0{1}v1q-0.5,{2} -1,0{3}z'/>" -f (
        $(if ($Upwards) {-$Amplitude} else {$Amplitude}),
        ("t1,0" * ($HalfWaves - 1)),
        $(if ($Upwards -xor ($HalfWaves % 2 -eq 0)) {-$Amplitude} else {$Amplitude}),
        ("t-1,0" * ($HalfWaves - 1))
    )
}

通过将变量放入字符串中,设置的区域设置似乎不适用于任何情况。

我在考虑如何简化设置,并想出了加速器:

Add-type -typedef @"
 using System;  

 public class InvFloat  
 {  
     double _f = 0;  
     private InvFloat (double f) {  
         _f = f;
     }  
     private InvFloat(string f) {  
         _f = Double.Parse(f, System.Globalization.CultureInfo.InvariantCulture);
     }  
     public static implicit operator InvFloat (double f) {  
         return new InvFloat(f);  
     }  
     public static implicit operator double(InvFloat f) {  
         return f._f;
     }  
     public static explicit operator InvFloat (string f) {  
         return new InvFloat (f);
     }  
     public override string ToString() { 
         return _f.ToString(System.Globalization.CultureInfo.InvariantCulture); 
     }
 }  
"@
$acce = [type]::gettype("System.Management.Automation.TypeAccelerators") 
$acce::Add('f', [InvFloat])
$y = 1.5.ToString()
$z = ([f]1.5).ToString()

我希望它能有所帮助。

这是一个PowerShell函数,我用于在其他文化中测试脚本。我相信它可以用于你所追求的:

function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
                        [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
{    
    $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
    $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
    try {
        [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
        [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture        
        Invoke-Command $script    
    }    
    finally {        
        [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture        
        [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture    
    }    
}

PS> $res = Using-Culture fr-FR { 1.1 }
PS> $res
1.1
While向您展示了如何按需更改脚本的当前区域性(从PSv3+和.NET framework v4.6+开始更为现代的替代方案):
[cultureinfo]::CurrentCulture=[cultureinfo]::InvariantCulture
),无需更改区域性,因为正如您在第二次更新问题时所发现的那样,PowerShell的字符串插值(与使用
-f
运算符相反)始终使用不变量而不是当前区域性

换言之:

如果将
'val:{0}'-f 1.2
替换为
“val:$(1.2)”
,则文字
1.2
的格式将不符合当前区域性的规则。
您可以在控制台中通过运行(在单行上;PSv3+,.NET framework v4.6+)进行验证:


背景:

令人惊讶的是,PowerShell始终在以下与字符串相关的上下文中应用不变量,而不是当前区域性,如果当前类型支持特定于区域性的字符串转换:

如中所述,PowerShell在以下场景中通过传递实例显式请求区域性不变处理

  • 字符串插值时:如果对象的类型实现了
    IFormattable
    接口;否则,PowerShell将对对象调用
    .psobject.ToString()

  • 铸造时

    • 绑定到字符串,包括绑定到
      [string]
      类型化参数时:如果源类型实现了接口;否则,PowerShell将调用
      .psobject.ToString()
    • 来自字符串的:如果目标类型的静态
      .Parse()
      方法具有带类型参数的重载(这是由
      [cultureinfo]
      实现的接口)
  • 当比较字符串时(
    -eq
    -lt
    -gt
    ),使用

  • 其他人

至于目的是什么:

不变的文化是文化不敏感的;它与英语相关,但与任何国家/地区无关 […]
与区域性敏感数据不同,区域性敏感数据可能会因用户自定义或.NET Framework或操作系统的更新而发生更改,而不变的区域性数据随着时间的推移和安装的区域性之间保持稳定,用户无法自定义。这使得不变区域性对于需要独立于区域性的结果的操作特别有用,例如持久化格式化数据的格式化和解析操作,或者要求以固定顺序显示数据而不考虑区域性的排序和排序操作

大概是跨文化的稳定性促使PowerShell的设计人员在隐式转换字符串时始终使用不变文化

例如,如果您将日期字符串(如
'7/21/2017'
)硬编码为脚本,然后尝试使用
[date]
强制转换将其转换为日期,PowerShell的区域性不变行为可确保脚本在非美式英语的区域性有效时运行时不会收支平衡,不变区域性还识别ISO 8601格式的日期和时间字符串

e、 例如,
[datetime]“2017-07-21”
也很有效

另一方面,如果要在当前区域性适当的字符串之间进行转换,则必须明确地进行转换

总结如下:

  • 转换为字符串

    • “…”
      中嵌入默认情况下具有区域性敏感字符串表示的数据类型实例会产生区域性不变表示(
      [double]
      [datetime]
      就是此类类型的示例)
    • 要获取当前区域性表示,请显式调用
      .ToString()
      ,或使用
      -f
      ,格式化运算符(可能位于
      “…”
      内部,通过封闭的
      $(…)
  • 从字符串转换

    • 直接转换(
      []…
      )只能识别区域性不变的字符串表示形式

    • 要从当前区域性转换适当的字符串表示形式(或特定区域性的表示形式),请显式使用目标类型的静态
      ::Parse()
      方法(可选地使用显式
      [cultureinfo]
      实例来表示特定区域性)


区域性不变示例:
  • 字符串插值强制转换

    • “$(1/10)”
      [st
      
      function Using-Culture ([System.Globalization.CultureInfo]$culture =(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"),
                              [ScriptBlock]$script=(throw "USAGE: Using-Culture -Culture culture -Script {scriptblock}"))
      {    
          $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
          $OldUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture
          try {
              [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
              [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture        
              Invoke-Command $script    
          }    
          finally {        
              [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture        
              [System.Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture    
          }    
      }
      
      PS> $res = Using-Culture fr-FR { 1.1 }
      PS> $res
      1.1
      
       PS> [cultureinfo]::currentculture = 'de-DE'; 'val: {0}' -f 1.2; "val: $(1.2)"
       val: 1,2 # -f operator: GERMAN culture applies, where ',' is the decimal mark
       val: 1.2 # string interpolation: INVARIANT culture applies, where '.' is the decimal mark.
      
          #>Get-Culture
          LCID             Name             DisplayName                                                                                                                                             
      ----             ----             -----------                                                                                                                                             
      1031             de-DE            German (Germany)                                                                                                                                        
      
      #>Get-UICulture
      
      LCID             Name             DisplayName                                                                                                                                             
      ----             ----             -----------                                                                                                                                             
      1033             en-US            English (United States) 
      
      PS Home:> $d=1.23
      PS Home:> $d
      1,23
      
      $d.ToString([cultureinfo]::CurrentUICulture)
      1.23