Числа меняются внутри переменных для powershell - PullRequest
1 голос
/ 22 апреля 2020

Я буквально просто пытаюсь преобразовать строку с информацией о неделе и дне в числа и сохранить ее как переменную, но что-то действительно странное происходит, на данный момент я проверил это поведение на 4 ПК, а в Powershell 5 и 7 это происходит повсеместно.

$UP_Down = "6w0d"

[int]$weeks = if ($Up_Down -match "w"){$Up_Down[$($Up_Down.IndexOf('w')-1)]}Else{0}

[int]$days = if ($Up_Down -match "d"){$Up_Down[$Up_Down.IndexOf('d')-1]}Else{0}

[int]$totaldays = (7 * $weeks) + $days

Теперь данные из начальной переменной, очевидно, 6 недель и 0 дней , в которые я должен преобразовать 42 Всего дней (это всего лишь пример, это происходит независимо от комбинации)

Однако ниже приведены результаты Funky, которые я получил, Write-Output

Weeks If statement results by itself 6
Weeks variable results 54
days If statement results by itself 0
days variable results  48
totaldays variable results are 426

Проблема возникает независимо от того, какой номер c тип данных я использую

По иронии судьбы переменные имеют правильное значение, если я НЕ присваиваю им тип данных, НО ,

в тот момент, когда оно достигает (7*$weeks), даже если $weeks является верным значением, выданным 426 , и помните, что нет [int] et c в любом месте

Что я делаю неправильно?

Ответы [ 3 ]

2 голосов
/ 22 апреля 2020

Вы индексируете ([...]) в строку $Up_Down, что означает вы возвращаете один символ , то есть [char] (System.Char) экземпляр .

Приведение [char] к [int] дает его кодовую точку Unicode ("значение ASCII "), не ди git, который символ представляет.

Например, символ 6 является символом Unicode DI GIT SIX с кодовой точкой U+0036; 0036 является шестнадцатеричной формой числовой c кодовой точки, а десятичная форма шестнадцатеричного 0x36 является 54.

PS> [int] "6w0d"[0]
54 # !! Same as: [int] [char] "6"

Для интерпретации символа как di git, вам нужен промежуточный [string] каст :

PS> [int] [string] "6w0d"[0]
6   # OK - a string is parsed as expected; same as: [int] "6"

Если вы используете строку вместо char до [int], PowerShell эффективно вызывает System.Int32.Parse за кадром следующим образом: [int]::Parse($string, [cultureinfo]::InvariantCulture).

Обратите внимание, что PowerShell имеет нет char литералы - в отличие от C#, '...' цитирование также создает строки (дословные), а [int] '6' дает целое число 6, как и [int] "6".

И наоборот, вам необходимо явное приведение [char] для преобразования односимвольного строкового литерала в [char]; например, [char] '6'; многосимвольная строка вызовет приведение к fail .


Решение в контексте вашей команды:

[int]$weeks = if ($Up_Down -match "w"){[string] $Up_Down[$Up_Down.IndexOf('w')-1]} Else {0}

[int]$days = if ($Up_Down -match "d"){[string] $Up_Down[$Up_Down.IndexOf('d')-1]} Else {0}

Однако Я предлагаю решить проблему по-другому :

[int] $totalDays = 0
if ($UP_Down -match '^(?:(?<weeks>\d+)w)?(?:(?<days>\d+)d)?$') {
  [int] $weeks, [int] $days = $Matches.weeks, $Matches.days
  $totalDays = 7 * $weeks + $days
} # else: string wasn't in expected format.
2 голосов
/ 22 апреля 2020

Проблема в том, что вы преобразуете не число внутри строки "6" в число 6, а символ '6' в его значение в соответствии с базовой схемой кодировки символов, которая равна 54 в случае ASCII. То же самое со днем: '0' имеет значение 48. 7 * 54 + 48 = 426.

См. Разницу:

PS C:\Users\name> [int]"6"[0]
54
PS C:\Users\name> [int]"6"
6

При извлечении элемента строки посредством индексации с [0] вместо строки длины 1 вы получите символ. Приведение к int вернет значение ASCII этого символа.

1 голос
/ 22 апреля 2020

другие показали вам, почему проблема затронула вас, так что это просто альтернативный способ подсчета общего количества дней. [ ухмылка ]

что он делает ...

  • подделывает чтение в текстовом файле с кодами недели / дня
    , когда готов использовать реальные данные , удалите весь блок #region/#endregion и используйте Get-Content.
  • перебирает список
  • разбивает на w
  • обрезает завершающий d
  • назначает результирующие строки двум [int] переменные слева от =
    заставляют две числовые строки стать числом объектов .
  • подсчитывает общее количество дней
  • отображает код недели / дня, количество недель, количество дней и общее количество дней

код ...

#region >>> fake reading in a list of week/day codes
#    in real life use Get-Content
$WD_List = @'
6w0d
3w3d
0w1d
66w6d
9w1d
'@ -split [System.Environment]::NewLine
#endregion >>> fake reading in a list of week/day codes

foreach ($WL_Item in $WD_List)
    {
    [int]$WeekCount, [int]$DayCount = $WL_Item.Split('w').TrimEnd('d')
    $TotalDays = ($WeekCount * 7) + $DayCount


    $WL_Item
    $WeekCount
    $DayCount
    $TotalDays
    '=' * 20
    }

выход ...

6w0d
6
0
42
====================
3w3d
3
3
24
====================
0w1d
0
1
1
====================
66w6d
66
6
468
====================
9w1d
9
1
64
====================
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...