Domanda

C'è un modo semplice in PowerShell per formattare i numeri e come in un altro locale?Attualmente sto scrivendo un paio di funzioni per facilitare SVG generazione per me e SVG usa . come separatore decimale, mentre PowerShell onori la mia lingua impostazioni (de-DE quando si converte i numeri in virgola mobile per le stringhe.

C'è un modo semplice per impostare un altro locale per una funzione o senza attaccare

.ToString((New-Object Globalization.CultureInfo ""))

dopo ogni double variabile?

Nota:Questo è circa il locale usato per la formattazione, non la stringa di formato.

(Lato domanda:Devo usare la lingua inglese, in quel caso, o piuttosto en-US?)

ETA: Beh, quello che sto cercando è qualcosa di simile al seguente:

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))
    )
}

Solo un po ' di automazione per le cose tendo a scrivere tutto il tempo e il doppio valori di utilizzare il separatore decimale il punto invece della virgola (che uso nel mio locale).

ETA2: Interessante curiosità da aggiungere:

PS Home:> $d=1.23
PS Home:> $d
1,23
PS Home:> "$d"
1.23

Mettendo la variabile in una stringa il set locale non sembra applicare, in qualche modo.

È stato utile?

Soluzione

Questo è un uso che funzione di PowerShell per testare lo script in altre culture. Credo che potrebbe essere utilizzato per quello che stai cercando:

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

Altri suggerimenti

Mentre Keith Hill risposta utile mostra come modificare uno script cultura corrente on demand (più moderna alternativa di PSv3+ e .NET framework v4.6+:
[cultureinfo]::CurrentCulture = [cultureinfo]::InvariantCulture), c'è non c'è bisogno di cambiare la cultura, perché - come hai scoperto il tuo secondo aggiornamento per la questione - PowerShell stringa interpolazione (in alternativa all'uso del -f operatore) utilizza sempre la invariante piuttosto che il corrente cultura:

In altre parole:

Se si sostituisce 'val: {0}' -f 1.2 con "val: $(1.2)", il valore letterale 1.2 è non formattato secondo le regole della cultura corrente.
È possibile verificare nella console di esecuzione (su una sola riga;PSv3+, .NET framework v4.6+):

 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.

Sfondo:

Sorprendentemente, PowerShell sempre si applica la invariante piuttosto che il corrente cultura nel seguente stringa correlati contesti, se il tipo a portata di mano sostiene la cultura specifica di conversione da e per le stringhe:

Come spiegato in questa approfondita risposta, PowerShell esplicitamente richieste cultura-invariante elaborazione - passando l' [cultureinfo]::InvariantCulture esempio - nei seguenti scenari:

  • Quando string-interpolazione:se il tipo di oggetto implementa l' IFormattable interfaccia;in caso contrario, PowerShell chiamate .psobject.ToString() sull'oggetto.

  • Quando casting:

    • per una stringa, anche quando l'associazione a un [string]digitato il parametro:se il tipo di origine implementa l' [IFormattable] interfaccia;in caso contrario, PowerShell chiamate .psobject.ToString().
    • da una stringa:se la destinazione di tipo statico .Parse() il metodo ha un sovraccarico con un [IFormatProvider]digitato il parametro (che è un'interfaccia implementata da [cultureinfo]).
  • Quando string-confronto (-eq, -lt, -gt) , utilizzando il String.Compare() overload che accetta un CultureInfo parametro.

  • Gli altri?

Per quanto le impostazioni cultura invarianti è / è per:

La lingua inglese è lingua;è associato con la lingua inglese, ma non con qualsiasi paese/regione.
[...]
A differenza di cultura-dati sensibili, soggette a modifica da parte di personalizzazione da parte dell'utente o da aggiornamenti al .NET Quadro o il sistema operativo, impostazioni cultura invarianti dati stabile nel tempo e tra installato culture e non può essere personalizzato dagli utenti.Questo rende le impostazioni cultura invarianti particolarmente utile per le operazioni che richiedono cultura-risultati indipendenti, come ad esempio la formattazione e le operazioni di analisi, che continuano a persistere i dati formattati o l'ordinamento e l'ordinamento di operazioni che richiedono che i dati visualizzati in un ordine fisso a prescindere dalla cultura.

Presumibilmente, è la stabilità attraverso le culture che hanno motivato PowerShell progettisti di utilizzare sempre l'invariante di cultura quando implicitamente conversione da e stringhe.

Per esempio, se è rigido codice di una data stringa, ad esempio '7/21/2017' in uno script e successivamente si tenta di convertire la data con un [date] il cast, PowerShell cultura-invariante comportamento assicura che lo script non si rompe anche se per l'esecuzione, mentre una cultura diversa dall'inglese (USA è in vigore - fortunatamente, la lingua inglese riconosce anche ISO 8601-formato di data e ora stringhe;
ad esempio, [datetime] '2017-07-21' lavora troppo.

Il rovescio della medaglia, se si desidera convertire da e per corrente-cultura-le stringhe appropriate, si deve fare così in modo esplicito.

Per riassumere:

  • La conversione per stringhe:

    • Incorporamento di istanze di tipi di dati con sensibile alla cultura-by-default rappresentazioni di stringa all'interno "..." produce una culturainvariante rappresentazione ([double] o [datetime] sono esempi di questi tipi).
    • Per ottenere un corrente-cultura rappresentazione, chiamata .ToString() in modo esplicito o utilizzare -f, la formattazione operatore (eventualmente all'interno "..." tramite un allegando $(...)).
  • La conversione da stringhe:

    • Diretta cast ([<type>] ...) sempre e solo riconosce la cultura-invariante rappresentazioni di stringa.

    • Per la conversione da un corrente-cultura-adeguata rappresentazione in forma di stringa (o un specifiche la cultura della rappresentazione), utilizzare il tipo di target statico ::Parse() metodo in modo esplicito (facoltativamente con un esplicito [cultureinfo] istanza di rappresentare una cultura specifica).


Cultura-INVARIANTE esempi:

  • stringa di interpolazione e cast:

    • "$(1/10)" e [string] 1/10

      • sia resa letterale di stringa 0.1, con separatore decimale ., a prescindere dalla cultura corrente.
    • Allo stesso modo, cast da stringhe sono cultura-invariante;ad esempio, [double] '1.2'

      • . è sempre riconosciuto come separatore decimale, a prescindere dalla cultura corrente.
      • Un altro modo di dirlo: [double] 1.2 è non tradotto per la cultura-sensibiliper impostazione predefinita overload del metodo [double]::Parse('1.2'), ma per la cultura-invariante [double]::Parse('1.2', [cultureinfo]::InvariantCulture)
  • per il confronto di stringhe (si supponga che [cultureinfo]::CurrentCulture='tr-TR' è, in effetti, - bagno turco, dove i NON è una minuscola rappresentanza di I)

    • [string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')
      • $false con la cultura turca in vigore.
      • 'i'.ToUpper() mostra che nella cultura turca il maiuscolo è İ, non I.
    • 'i' -eq 'I'
      • è ancora $true, perché il invariante la cultura è applicato.
      • implicitamente lo stesso: [string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')

SENSIBILE alla cultura esempi:

La cultura attuale È rispettato nei seguenti casi:

  • Con -f, la stringa di formattazione operatore (come indicato sopra):

    • [cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2 i rendimenti 1,2
    • Insidia:A causa di precedenza degli operatori, qualsiasi espressione come RHS della -f deve essere racchiusa in (...) per essere riconosciuto come tale:
      • E. g., '{0}' -f 1/10 viene valutato come se ('{0}' -f 1) / 10 era stato specificato;
        utilizzare '{0}' -f (1/10) invece.
  • Di Default in uscita per la console:

    • ad esempio, [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 i rendimenti 1,2

    • Lo stesso vale per l'output dei cmdlet;ad esempio,
      [cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01' i rendimenti
      Sonntag, 1. Januar 2017 00:00:00

    • Caveat:Sembra che ci sia un bug come di Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5:in alcuni scenari, valori letterali passato a un blocco di script come libera parametri può causare cultura-invariante di output di default - vedere questo problema GitHub

  • Durante la scrittura di un file con Set-Content/Add-Content o Out-File / > / >>:

    • ad esempio, [cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt i rendimenti 1,2
  • Quando si utilizza la statica ::Parse() / ::TryParse() metodi sul numero di tipi come [double] mentre passa solo la stringa da analizzare;ad esempio, con la cultura fr-FR in effetti (dove , è il separatore decimale), [double]::Parse('1,2') restituisce il doppio 1.2 (cioè, 1 + 2/10).

    • Caveat:Come bviktor sottolinea, di un separatore di migliaia riconosciuto per impostazione predefinita, ma in un modo molto sciolto moda:effettivamente, il separatore delle migliaia può essere collocato ovunque all'interno la parte intera, indipendentemente dal numero di cifre sono gruppi risultanti, e un leader 0 inoltre è accettato;ad esempio, nel en-US cultura (dove , è il separatore delle migliaia), [double]::Parse('0,18') forse sorprendentemente riesce e rendimenti 18.
      • Per sopprimere il riconoscimento di un separatore di migliaia, usare qualcosa come [double]::Parse('0,18', 'Float'), via NumberStyles parametro
  • Involontaria la cultura di una sensibilità non essere corretti per mantenere la compatibilità all'indietro:

  • Gli altri?

Stavo pensando a come rendere più facile e si avvicinò con acceleratori:

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()

Spero che sarà di aiuto.

Se avete già la cultura caricato nel proprio ambiente,

    #>Get-Culture
    LCID             Name             DisplayName                                                                                                                                             
----             ----             -----------                                                                                                                                             
1031             de-DE            German (Germany)                                                                                                                                        

#>Get-UICulture

LCID             Name             DisplayName                                                                                                                                             
----             ----             -----------                                                                                                                                             
1033             en-US            English (United States) 

è possibile risolvere il problema:

PS Home:> $d=1.23
PS Home:> $d
1,23

in questo modo:

$d.ToString([cultureinfo]::CurrentUICulture)
1.23

Naturalmente è necessario tenere a mente che se gli altri utenti di eseguire lo script con un'impostazione locale diversa, i risultati potrebbero non risultare come originariamente previsto.

Tuttavia, questa soluzione potrebbe tornare utile. Buon divertimento!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top