#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
}
}
}
}
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 в качестве результата. Теперь я не очень хорошо разбираюсь в регулярных выражениях, этот пример будет работать только в том случае, если в файлах / папках нет пробелов. Если кто-нибудь может помочь с правильным регулярным выражением, чтобы разделить его, это было бы здорово: