如何在 PowerShell 中将命令的结果转换为二维数组?

时间:2021-03-24 23:48:14

标签: 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"
]

目标

有没有一种快速的方法可以把它变成一个二维数组,比如:

[
  [
    "-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"
  ]
]

本质上,这类似于将 object 转换为 array

如何在 PowerShell 中将命令的结果转换为二维数组?

2 个答案:

答案 0 :(得分:2)

要制作与您展示的完全一样的二维数组,您可以这样做。

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

enter image description here


然而,为了让可用的对象具有属性,我喜欢这个秘诀。

  • 切换语句
  • 正则表达式就够了
  • 一些字符串操作
  • 一元运算符
  • PSCustomObject
    $output = switch -Regex (ls -l){
        '(.+?)\s(\w{3}\s.+?:\d{1,})\s(.+?)$' {
            , -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

输出 enter image description here

TL;DR

switch 语句非常适合读取来自文件、命令输出等的行。我们只抓取那些与正则表达式匹配的行。

正则表达式说明

  • .+? 表示匹配任意数量的任意字符,但尽可能少。
  • ( ) 将任何与括号中的模式匹配的内容放入捕获组中。默认情况下将编号为组,如果您愿意,可以为它们命名。
  • \s 匹配单个空格
  • \w{3} 匹配 3 个单词字符
  • : 匹配文字冒号
  • \d{1,} 匹配一位或多位数字
  • $ 行尾。 (在此之前的匹配必须在行尾)

因此我们捕获 $matches.1 中的前 5 列、$matches.2 中的时间戳以及 $matches.3 中的其余文本(应该是文件/文件夹名称)

从那里我们通过将拆分放在首位来拆分 $matches.1。通常,当您拆分并向下发送管道时,它一次一个。

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

enter image description here

通过在前面添加逗号将其转换为数组并按原样发送到管道中。

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

enter image description here

然后我们只需将每个值放在正确的位置。也可以转成 JSON 对象。

enter image description here

答案 1 :(得分:1)

有了这个,您可以将 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]
    }
}

这是对象的外观: enter image description here