Как правильно сохранить строки с пробелами между символами (Массив)? - PullRequest
0 голосов
/ 10 января 2019

Два примера строк:

Bob                     02 02 10 80   Enquiries            
Martin      Corp        02 02 10 80   Langar               

Обратите внимание, что в первой строке нет информации после "Bob", поэтому просто пробелы.

Так что мой код будет:

$account_name = $inputFileContent[$i].Split(" ",[System.StringSplitOptions]::RemoveEmptyEntries)

Edit: Мой выходной массив должен выглядеть так:

$account_name =
Bob
(Empty Line)
02
02
10
80
Enquiries

Есть ли способ изменить код, чтобы я сохранил его в массиве в этом формате?

Ответы [ 3 ]

0 голосов
/ 10 января 2019

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

Вот пример строки, в которую я добавил индексную нумерацию выше:

 012345678901234567890123456789012345678901234567890
  Martin      Corp        02 02 10 80   Langar

Вы можете заметить, что первое значение Martin начинается со второго символа, номер индекса 1 и имеет длину не более 12 символов. Второе значение Corp начинается с индекса 13 и имеет длину не более 11 символов, после чего начинается первое значение 02 и т. Д.

Мы используем substring(1,12), чтобы получить срез длиной 12 символов из строки, начинающейся с индекса 1. Чтобы удалить (завершающий) пробел из строки, мы вызываем метод Trim().

Для создания нового объекта, содержащего данные каждой строки, мы используем [PSCustomObject] и присваиваем имена свойствам объекта или заголовкам, если хотите. += оператор добавляет этот объект в массив.

test.txt

 Bob                     02 02 10 80   Enquiries            
 Martin      Corp        02 02 10 80   Langar

Сценарий:

$array = @() # Create an empty array

Get-Content .\test.txt | foreach{ # Read test.txt file and handle each line with foreach
    $array += [PSCustomObject]@{
        Field1 = $_.substring(1,12).Trim();
        Field2 = $_.substring(13,11).Trim();
        Field3 = $_.substring(25,2).Trim();
        Field4 = $_.substring(28,2).Trim();
        Field5 = $_.substring(31,2).Trim();
        Field6 = $_.substring(34,2).Trim();
        Field7 = $_.substring(39); # Substring from index 39 to the end of line
    }
}

$array

Чтобы вывести значения, каждое из которых находится в отдельной строке, вы можете сделать это, например, так:

$array | foreach{
    $_.Field1
    $_.Field2
    $_.Field3
    $_.Field4
    $_.Field5
    $_.Field6
    $_.Field7
}
0 голосов
/ 11 января 2019

ConvertFrom-SourceTable

Некоторое время назад я создал ConvertFrom-SourceTable командлет для чтения фиксированных таблиц, подобных вашей:

$Text = @'
 Bob                     02 02 10 80   Enquiries
 Martin      Corp        02 02 10 80   Langar
'@

-header

Поскольку у вашего $Text примера нет заголовка, вам просто нужно предоставить его, убедившись, что каждый заголовок столбца выровнен с данными столбца, например ::

ConvertFrom-SourceTable $Text -Header @'
 Name        Company     A  B  C  D    Comment
'@ | Format-Table

Name   Company A  B  C  D  Comment
----   ------- -  -  -  -  -------
Bob            02 02 10 80 Enquiries
Martin Corp    02 02 10 80 Langar

02 02 10 80

Командлет ConvertFrom-SourceTable довольно умен, определяя, где столбцы должны начинаться и заканчиваться. В вашем примере, если 02 02 10 80 на самом деле один столбец, вы можете просто добавить заголовок одного столбца для этого столбца:

ConvertFrom-SourceTable $Text -Header @'
 Name        Company     Code          Comment
'@ | Format-Table

Name   Company Code        Comment
----   ------- ----        -------
Bob            02 02 10 80 Enquiries
Martin Corp    02 02 10 80 Langar

Пока вы держите окружающие столбцы Company и Comment (включая заголовок) также выровненными влево. Если это не так (и в некоторых редко других ситуациях), вы также можете добавить параметр -Ruler (см. Help ConvertFrom-SourceTable -Full) для дальнейшего определения выравнивания таблицы.

Специфично для вашего ответа:

Как видно из примера, командлет ConvertFrom-SourceTable возвращает список объектов (общих для большинства других командлетов), которые можно легко передавать на собственные командлеты, такие как Where-Object и ForEach-Object. В вашем конкретном случае вы можете сделать что-то вроде этого:

$Accounts = ConvertFrom-SourceTable $Text -Header @'
 Name        Company     A  B  C  D    Comment
'@

(($Accounts | Where-Object {$_.Name -eq 'Bob'}).PSObject.Properties).Value

В результате:

Bob

02
02
10
80
Enquiries
0 голосов
/ 10 января 2019

Одна из возможностей - использовать регулярные выражения:

Get-Content "data.txt" | ForEach-Object {
    $_ -match "^([a-z]+) +(\w*) +((?:\d{2} ){3}\d{2}) +(\w+)$" | Out-Null

    $account_name = 1..4 | ForEach-Object {$matches[$_]}
}

Это установит $account_name в:

Bob

02 02 10 80
Enquiries

или

Martin
Corp
02 02 10 80
Langar

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

Примечание: Я предположил, что вы на самом деле хотели, чтобы «код» был как один элемент (например, «02 02 10 80»), но если нет, шаблон можно отрегулировать, чтобы вытащить отдельные элементы.

...