Хотя Полезный ответ Кейта Хилла показывает, как изменить текущую культуру сценария по требованию (более современная альтернатива для 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 +):
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.
Справочная информация:
Удивительно, но PowerShell всегда применяет инвариант вместо текущей культуры в следующих связанных со строками контекстах , , если , данный тип поддерживает преобразование в зависимости от культуры в и из строк:
Как объяснено в в этом подробном ответе , PowerShell явно запрашивает инвариантную культуру обработку - путем передачи [cultureinfo]::InvariantCulture
экземпляр - в следующих сценариях:
Когда интерполяция строк : если тип объекта реализует интерфейс IFormattable
; в противном случае PowerShell вызывает .psobject.ToString()
для объекта.
При кастинге :
При сравнении строк (-eq
, -lt
, -gt
) с использованием перегрузки String.Compare()
, которая принимает параметр CultureInfo
.
Другие
Для чего инвариантная культура предназначена для:
Инвариантная культура нечувствительна к культуре; связано с английским языком, но не с какой-либо страной / регионом .
[...]
В отличие от чувствительных к культуре данных, которые могут изменяться пользовательской настройкой или обновлениями .NET Framework или операционной системы, инвариантные данные культуры стабильны во времени во всех установленных культурах и не могут настраиваться пользователями , Это делает инвариантную культуру особенно полезной для операций, которые требуют независимых от культуры результатов, таких как операции форматирования и синтаксического анализа, которые сохраняют отформатированные данные, или операции сортировки и упорядочения, которые требуют, чтобы данные отображались в фиксированном порядке независимо от культуры.
Предположительно, именно стабильность в разных культурах побудила разработчиков PowerShell последовательно использовать инвариантную культуру, когда неявно конвертирует в и из строк .
Например, если вы жестко закодировали строку даты, такую как '7/21/2017'
, в сценарий, а затем попытались преобразовать ее в дату с помощью приведения [date]
, поведение PowerShell, не зависящее от культуры, гарантирует, что сценарий не будет разбит даже когда запускается, когда действует культура, отличная от американского-английского - к счастью, инвариантная культура также распознает строки даты и времени в формате ISO 8601 ;
например, [datetime] '2017-07-21'
тоже работает.
С другой стороны, , если вы хотите преобразовать в текущие -культурные строки, соответствующие *, вы должны сделать это явно .
Подведем итог:
Культурно-инвариантные примеры:
интерполяция строки и приведение :
"$(1/10)"
и [string] 1/10
- оба дают строковый литерал
0.1
, с десятичной отметкой .
, независимо от текущей культуры.
Аналогично, приведение из строки являются культурно-инвариантными; например, [double] '1.2'
.
всегда распознается как десятичный знак независимо от текущей культуры.
- Другой способ выразить это:
[double] 1.2
- это не , переведенный в культуру - чувствительный - по умолчанию перегрузка метода [double]::Parse('1.2')
, но в культуру- инвариант [double]::Parse('1.2', [cultureinfo]::InvariantCulture)
сравнение строк (предположим, что действует [cultureinfo]::CurrentCulture='tr-TR'
- турецкий, где i
НЕ является строчным представлением I
)
[string]::Equals('i', 'I', 'CurrentCultureIgnoreCase')
$false
с действующей турецкой культурой.
'i'.ToUpper()
показывает, что в турецкой культуре заглавными буквами является İ
, а не I
.
'i' -eq 'I'
- по-прежнему
$true
, потому что применяется культура инвариант .
- неявно совпадает с:
[string]::Equals('i', 'I', 'InvariantCultureIgnoreCase')
Культурочувствительные примеры:
Нынешняя культура соблюдается в следующих случаях:
С -f
, оператором форматирования строки (как отмечено выше):
[cultureinfo]::currentculture = 'de-DE'; '{0}' -f 1.2
выход 1,2
- Подводный камень: Из-за оператора приоритета любое выражение в качестве RHS
-f
должно быть заключено в (...)
для того, чтобы быть признанным в качестве такового:
- Например,
'{0}' -f 1/10
оценивается так, как если бы было указано ('{0}' -f 1) / 10
;
используйте '{0}' -f (1/10)
вместо.
По умолчанию вывод на консоль :
например, [cultureinfo]::CurrentCulture = 'de-DE'; 1.2
выход 1,2
То же самое относится к выводу из командлетов; например.,
[cultureinfo]::CurrentCulture = 'de-DE'; Get-Date '2017-01-01'
урожайность
Sonntag, 1. Januar 2017 00:00:00
Предупреждение : Похоже, что ошибка в Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5: в некоторых сценариях проходили литералы в блок скрипта, так как неограниченные параметры могут привести к выводу по умолчанию, инвариантному к культуре - см. эту проблему GitHub
При записи в файл с Set-Content
/ Add-Content
или Out-File
/ >
/ >>
:
- например,
[cultureinfo]::CurrentCulture = 'de-DE'; 1.2 > tmp.txt; Get-Content tmp.txt
выход 1,2
При использовании статических методов ::Parse()
/ ::TryParse()
для числовых типов, таких как [double]
, при передаче только строки для анализа; например, при действующей культуре fr-FR
(где ,
- десятичная отметка), [double]::Parse('1,2')
возвращает двойной 1.2
(т.е. 1 + 2/10
).
- Предостережение : Как указывает bviktor , разделители тысяч распознаются по умолчанию, но очень свободно: фактически разделитель тысяч можно разместить в любом месте внутри целочисленной части, независимо от того, сколько цифр в результирующих группах, и также допускается начальный
0
; например, в культуре en-US
(где ,
- разделитель тысяч), [double]::Parse('0,18')
, возможно, на удивление , следует и дает 18
.
- Чтобы подавить распознавание тысяч разделителей, используйте что-то вроде
[double]::Parse('0,18', 'Float')
через параметр NumberStyles
Непреднамеренная чувствительность к культуре, которая не будет исправлена для сохранения обратной совместимости :
Другие