Как преобразовать результат выполнения команды в 2D-массив в PowerShell?

#json #powershell

Вопрос:

Известный

Рассмотрим следующую команду:

ls -l

 -rwx------  123 ladiesman217  root    549 Apr 01 01:01 one.txt
-rwx------  123 ladiesman217  root    549 Apr 01 02:02 two.txt
-rwx------  123 ladiesman217  root    549 Apr 01 03:03 three.txt
 

При передаче по каналу ConvertTo-Json он создает массив примерно так:

ls -l | ConvertTo-Json

 [
  "-rwx------  123 ladiesman217  root    549 Apr 01 01:01 one.txt",
  "-rwx------  123 ladiesman217  root    549 Apr 01 02:02 two.txt",
  "-rwx------  123 ladiesman217  root    549 Apr 01 03:03 three.txt"
]
 

Цель

Есть ли быстрый способ превратить его в 2d массив, что-то вроде:

 [
  [
    "-rwx------",
    "123",
    "ladiesman217",
    "root",
    "549",
    "Apr",
    "01",
    "01:01",
    "one.txt"
  ],
  [
    "-rwx------",
    "123",
    "ladiesman217",
    "root",
    "549",
    "Apr",
    "01",
    "02:02",
    "two.txt"
  ],
  [
    "-rwx------",
    "123",
    "ladiesman217",
    "root",
    "549",
    "Apr",
    "01",
    "03:03",
    "three.txt"
  ]
]
 

По сути, это было бы что-то вроде преобразования an object в an array .

Как преобразовать результат выполнения команды в 2D-массив в PowerShell?

Комментарии:

1. Это сработало для меня, но только в том случае, если в файлах / папках нет пробелов ls -l|select -skip 1|%{$_ -split 's{1,}'|convertto-json} . Обратите внимание, что я использую select -skip 1 , потому что в pwsh в Linux первая строка дает вам общее количество.

2. Я собираюсь опубликовать ответ, чтобы показать вам, как он выглядит для меня, и удалить его после. У меня нет никаких ошибок при его запуске.

3. @SantiagoSquarzon Я попробовал ваш пример, но, похоже, в нем синтаксис, отличный от json , выглядит так: [...][...][...] . Но это что-то (почти есть)

4. Да, я знаю. У вас также возникнет проблема, когда вы столкнетесь с полем / папкой с пробелами. Вам будет проще преобразовать ls -l в PSCustomObject, а затем преобразовать этот объект в JSON imo.

Ответ №1:

Чтобы создать 2D-массив точно так, как вы показали, вы можете сделать это.

    ls -l | Select-Object -Skip 1 | %{, -split $_ | ConvertTo-Json}
 

введите описание изображения здесь


Однако вместо того, чтобы создавать полезные объекты со свойствами, мне нравится этот рецепт.

  • Оператор переключения
  • Просто достаточно регулярных выражений
  • Щепотка манипуляций со струнами
  • Унарный оператор
  • PSCustomObject
     $output = switch -Regex (ls -l){
        '(. ?)s(w{3}s. ?:d{1,})s(. ?)

Выход
введите описание изображения здесь

TL;DR

Оператор switch отлично подходит для чтения строк, будь то из файла, вывода команд и т. Д. Мы берем только те строки, которые соответствуют шаблону регулярного выражения.

Объяснение регулярного выражения

  • . ? говорит, чтобы соответствовать любому количеству любого символа, но как можно меньше.
  • ( ) помещает все, что соответствует шаблону в скобках, в группу захвата. По умолчанию будут пронумерованы группы, можете назвать их, если хотите.
  • s сопоставьте один пробел
  • w{3} сопоставьте 3 символа слов
  • : сопоставьте буквальное двоеточие
  • d{1,} сопоставьте одну или несколько цифровых цифр
  • $ в конце очереди. (совпадение прямо перед этим должно быть в конце строки)
Поэтому мы записываем первые 5 столбцов $matches.1 , отметку $matches.2 времени и остальную часть текста (которая должна быть именем файла/папки) в $matches.3 Оттуда мы разделяемся $matches.1 на промежутки, ставя разделение первым. Обычно, когда вы разделяетесь и отправляете по конвейеру, это происходит по одному за раз.
 -split "a b c" | %{"$_"}
 

введите описание изображения здесь

Добавляя запятую спереди, которая превращает ее в массив и отправляется по конвейеру как таковая.

 , -split "a b c" | %{"$_"}
 

введите описание изображения здесь

Затем мы просто помещаем каждое значение в нужное место. Вы также можете превратиться в объект JSON.

введите описание изображения здесь

Ответ №2:

С помощью этого вы можете преобразовать результат ls -l в объект PS, который затем может быть передан ConvertTo-Json в случае, если вам понадобится Json в качестве результата. Теперь я не очень хорошо разбираюсь в регулярных выражениях, этот пример будет работать только в том случае, если в файлах / папках нет пробелов. Если кто-нибудь может помочь с правильным регулярным выражением, чтобы разделить его, это было бы здорово:

 $lsObject=ls -l|select -skip 1|%{
    $tmp=$_ -split 's{1,}'
    [PSCustomObject]@{
        Permission = $tmp[0]
        Links = $tmp[1]
        Owner = $tmp[2]
        Group = $tmp[3]
        Size = $tmp[4]
        LastModified = '{0} {1} {2}' -f $tmp[5],$tmp[6],$tmp[7]
        FileName = $tmp[8]
    }
}
 

Вот как выглядит объект:
введите описание изображения здесь

{
, -split $matches.1 | Foreach-Object {
[PSCustomObject]@{
Permission = $_[0]
Links = $_[1]
Owner = $_[2]
Group = $_[3]
Size = $_[4]
Modified = $matches.2
FileName = $matches.3
}
}
}
}

$output | Format-Table
Выход
введите описание изображения здесь

TL;DR

Оператор switch отлично подходит для чтения строк, будь то из файла, вывода команд и т. Д. Мы берем только те строки, которые соответствуют шаблону регулярного выражения.

Объяснение регулярного выражения

  • . ? говорит, чтобы соответствовать любому количеству любого символа, но как можно меньше.
  • ( ) помещает все, что соответствует шаблону в скобках, в группу захвата. По умолчанию будут пронумерованы группы, можете назвать их, если хотите.
  • s сопоставьте один пробел
  • w{3} сопоставьте 3 символа слов
  • : сопоставьте буквальное двоеточие
  • d{1,} сопоставьте одну или несколько цифровых цифр
  • $ в конце очереди. (совпадение прямо перед этим должно быть в конце строки)

Поэтому мы записываем первые 5 столбцов $matches.1 , отметку $matches.2 времени и остальную часть текста (которая должна быть именем файла/папки) в $matches.3

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


введите описание изображения здесь

Добавляя запятую спереди, которая превращает ее в массив и отправляется по конвейеру как таковая.


введите описание изображения здесь

Затем мы просто помещаем каждое значение в нужное место. Вы также можете превратиться в объект JSON.

введите описание изображения здесь

Ответ №2:

С помощью этого вы можете преобразовать результат ls -l в объект PS, который затем может быть передан ConvertTo-Json в случае, если вам понадобится Json в качестве результата. Теперь я не очень хорошо разбираюсь в регулярных выражениях, этот пример будет работать только в том случае, если в файлах / папках нет пробелов. Если кто-нибудь может помочь с правильным регулярным выражением, чтобы разделить его, это было бы здорово:


Вот как выглядит объект:
введите описание изображения здесь