Powershell выводит только первый символ

avatar
Henrov
1 июля 2021 в 16:29
119
2
1

У меня есть следующий набор данных:

 id|selectedquery|
 1|SELECT fieldX FROM tableA|
 2|SELECT fieldY FROM tableB|

этот набор данных используется в следующем коде

$rows=($dataSet.Tables | Select-Object -Expand Rows)
$i=0
foreach ($row in $rows)
{
#Write-Output $rows.selectquery[$i].length
$query =   $rows.selectquery[$i]
#Write-Output $rows.selectquery[$i]
--doing some stuff--
$i++
}

Часто $rows.selectquery[$i] дает мне только первый символ значения в поле selectedquery как 'S'.

Когда я удаляю [$i] из $rows.selectquery, это возвращает мне (понятно) несколько записей. Если я верну [$i] обратно после $rows.selectquery[$i], все будет хорошо.

Кто-нибудь может объяснить такое поведение?

Источник
Henrov
1 июля 2021 в 16:40
0

Конечно!!! Пожалуйста, поместите это как ответ? Ты заслуживаешь очков, а я заслуживаю наказания.

Steezy
1 июля 2021 в 16:57
1

Есть ли причина, по которой вы используете foreach с $row, но ссылаетесь на selectquery с [i], а не [$row]?

Henrov
2 июля 2021 в 09:58
0

ОП, иначе он мне все записи даст?

Ответы (2)

avatar
Mathias R. Jessen
1 июля 2021 в 17:00
3

Свойство SelectQuery нужно указать либо на $row, либо на $rows[$i] - не на всю $rows коллекцию:<21061555

$row.SelectQuery
# or
$rows[$i].SelectQuery

avatar
mklement0
1 июля 2021 в 18:52
1

Полезный ответ Матиаса показывает лучший способ решить вашу конкретную проблему.

Что касается что произошло:

Вы - непреднамеренно - использовали функцию PowerShell перечисления доступа к участникам, когда использовали $rows.selectquery; that is, even though $rows is a collection that itself has no .selectquery property, PowerShell accessed that property on every element of the collection and returned результирующие значения в виде массива .

The pitfall is that if the collection only has one element, the return value is not an array - it is just единственное значение свойства элемента само.

Хотя это аналогично тому, как работает конвейер (один объект вывода захватывается сам по себе, если он назначен переменной, в то время как два или более неявно собираются в массив), это несколько противоречит здравому смыслу в контекст перечисления доступа к членам:

  • Другими словами, $collection.SomeProperty эквивалентно $collection | ForEach-Object { $_.SomeProperty } и не, что было бы более разумно, поскольку всегда<4382529521515691> возвращает массив2 (23коллекция2)
  • GitHub issue #6802 обсуждает эту проблему.

Хотя такое поведение часто не вызывает проблем, поскольку PowerShell предлагает унифицированную обработку скаляров и коллекций (например, (42)[0] совпадает с самим 42; см. возникает, если возвращаемое единственное значение оказывается строкой, потому что индексирование в строку возвращает ее символы.

  • Временное решение: Приведение к [array] перед применением индекса:
    • ([array] $rows.selectquery)[0]

Простой пример:

# Multi-element array.
[array] $rows1 = [pscustomobject] @{ selectquery = 'foo' },
                 [pscustomobject] @{ selectquery = 'bar' }

# Single-element array:
[array] $rows2 = [pscustomobject] @{ selectquery = 'baz' }

# Contrast member-access enumeration + index access between the two:
[pscustomobject] @{
  MultiElement = $rows1.selectquery[0]
  SingleElement = $rows2.selectquery[0]
  SinglElementWithWorkaround = ([array] $rows2.selectquery)[0]
}

Вышеизложенное дает следующее:

MultiElement SingleElement SinglElementWithWorkaround
------------ ------------- --------------------------
foo                      b baz

Как видите, многоэлементный массив работал, как и ожидалось, потому что перечисление доступа к членам также возвращало массив, в то время как одноэлементный массив возвращал одну строку 'baz' и 'baz'[0] возвращает первый символ, 'b'.

Приведение к [array] сначала позволяет избежать этой проблемы (([array] $rows2.selectquery)[0]).