Как сохранить каждую строку текстового файла в виде массива через powershell - PullRequest
0 голосов
/ 04 сентября 2018

Если у меня есть текстовый файл, C: \ USER \ Documents \ Collections \ collection.txt со следующей информацией:

collectionA.json
collectionB.json
collectionC.json
collectionD.json

Мне интересно, как с помощью Powershell я могу сохранить каждую строку в текстовом файле в виде элементов массива, таких как ..

array arrayFromFile = new Array;
foreach(line x in collection.txt)
{
    arrayFromFile.Add(x);
}

.. с конечной целью сделать следующее:

foreach(string x in arrayFromFile)
{
    newman run x;
}

Приношу свои извинения за, казалось бы, простой вопрос - я никогда раньше не имел дела с Powershell.

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

В дополнение Полезный ответ Джона Л.Бевана :

Get-Content, как командлет , выводит объекты один за другим в конвейер , по мере их появления . (Обратите внимание, что конвейер задействуется при вызове командлета даже при отсутствии символа канала | для создания цепочки множественный команды).
В этом случае выходные объекты - это отдельные строки входного текстового файла.

Если вы собираете выходные объекты конвейера , например, , присваивая его переменной , например $arrayFromFile, или используя конвейер в контексте большего выражения с (...):

  • PowerShell захватывает несколько выходных объектов в автоматически создаваемом массиве типа [object[]],
  • но если имеется только один выходной объект, этот объект захватывается как есть ( без обертка массива)

Чтобы гарантировать, что выход конвейера будет всегда массивом, PowerShell предлагает @(...), оператор подвыражения массива , который переносит даже один -объект вывода в массив.

Поэтому идиоматическое решение PowerShell :

$arrayFromFile = @(Get-Content C:\USER\Documents\Collections\collection.txt)

Однако часто нет необходимости гарантировать, что вы всегда получите массив , потому что PowerShell обрабатывает скаляры (одиночные значения, которые не являются коллекциями), такие же, как массивы (коллекции) во многих контекстах, например в операторах foreach или при выводе значения, которое будет перечислено в конвейер.

TheMadTechnician указывает на то, что вы также можете использовать [Array] для приведения / типизации вывода конвейера в качестве альтернативы @(...), который также создает [object[]] массивы :

# Equivalent of the command above that additionally locks in the variable date type.
[Array] $arrayFromFile = Get-Content C:\USER\Documents\Collections\collection.txt

Используя [Array] $arrayFromFile = ... вместо $arrayFromFile = [Array] (...), переменная $arrayFromFile становится ограниченным по типу , что означает, что ее тип данных заблокирован (тогда как по умолчанию PowerShell позволяет вам изменять тип переменная в любое время).

[Array] - это независимая от команды альтернатива типу для конкретного типа , используемому в ответе Джона, [string[]]; вы можете использовать последний для принудительного использования единообразного типа для элементов массива, но это часто не требуется в PowerShell [1] .

Обычные массивы PowerShell относятся к типу [object[]], что позволяет смешивать элементы разных типов, но любой данный элемент все же имеет определенный тип; например, даже если тип $arrayFromFile после вышеприведенной команды равен [object[]], тип $arrayFromFile[0], т.е., например, 1-й элемент, равен [string] (при условии, что файл содержал хотя бы 1 строку; проверьте тип с $arrayFromFile[0].GetType().Name).


Более быстрая альтернатива: прямое использование .NET Framework

Командлеты и конвейер предлагают высокоуровневые, потенциально ограничивающие память функции, которые являются выразительными и удобными, но могут быть медленными .

Когда производительность имеет значение, необходимо прямое использование типов .NET Framework, например, [System.IO.File] в этом случае.

$arrayFromFile = [IO.File]::ReadAllLines('C:\USER\Documents\Collections\collection.txt')

Обратите внимание, как префикс System. может быть опущен в имени типа.

  • Как и в ответе Джона, это вернет массив [string[]].

  • Предостережения

    • Будьте осторожны с относительными путями, поскольку .NET обычно имеет другой текущий каталог, чем PowerShell; Чтобы обойти это, всегда пропускают абсолютные пути , например с "$PWD/collection.txt".

    • . По умолчанию для .NET используется кодировка UTF-8, тогда как Windows PowerShell по умолчанию использует кодировку "ANSI" , то есть устаревшую кодовую страницу языкового стандарта системы; PowerShell Core , напротив, также по умолчанию UTF-8. Используйте параметр Get-Encoding -Encoding или перегрузку .ReadAllLines(), которая принимает экземпляр кодировки, чтобы явно указать кодировку символов входного файла.


[1] Как правило, неявные преобразования типов во время выполнения PowerShell не могут обеспечить такую ​​же безопасность типов, как, например, в C #. Например, [string[]] $a = 'one', 'two'; $a[0] = 42 делает не причиной ошибки: PowerShell просто тихо преобразует [int] 42 в строку.

0 голосов
/ 04 сентября 2018

Команда Get-Content возвращает каждую строку из текстового файла в виде отдельной строки, поэтому вам будет предоставлен массив (если вы не используете параметр -Raw; в результате все строки объединяются в одна строка).

[string[]]$arrayFromFile = Get-Content -Path 'C:\USER\Documents\Collections\collection.txt'

В его превосходный ответ , mklement0 дает гораздо больше подробностей о том, что на самом деле происходит, когда вы вызываете эту команду, а также альтернативные подходы, если вы беспокоитесь о производительности, а не об удобстве. Определенно стоит прочитать, если вы хотите больше узнать о языке, а не просто решить одно требование.

...