Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将powershell数组转换为表_Powershell - Fatal编程技术网

如何将powershell数组转换为表

如何将powershell数组转换为表,powershell,Powershell,我在下面的链接中找到了一篇关于这个问题的类似帖子 我无法直接将其转换为表,因为缺少一些字段并执行操作 Customer ID Client Name Computer Name Computer Brand Duration Connection Time Lang 123 first last 127.0.0.1 lenovo

我在下面的链接中找到了一篇关于这个问题的类似帖子

我无法直接将其转换为表,因为缺少一些字段并执行操作

Customer ID        Client Name        Computer Name        Computer Brand        Duration        Connection Time        Lang
123                first last         127.0.0.1            lenovo                10:00           8/18/2019 6:00 PM      Eng
1                  lastname           127.0.0.2            apple                 2:30:00         8/18/2019 1:00 AM      Chn  
86                 user3              127.0.0.1            dell                                  8/18/2019 2:00 PM 
21                 user4              127.0.0.4            apple                 30:00           8/17/2019 1:00 PM      Eng
我想首先筛选连接时间超过30分钟的特定用户,然后列出其id

更新

结果应该是

1
21

因为它们的连接时间超过30分钟。

我想您在这里有一些要求。我将描述一种使用通用的“for循环”和正则表达式实现的方法——您可以根据需要使用和调整它。有更好的方法可以做到这一点(Powershell快捷方式),但是根据您询问的方式,我假设理解是您的目标,因此如果您有任何编程语言的背景,那么这段代码应该很有用。希望这有帮助

# Here is your data formatted in an array.  Missing values are just empty fields.
# You could have fewer or more fields, but I've broken up your data into nine fields
# (0-8 when counting elements in an array)

# Customer ID, FName, LName, ComputerHostName, Brand, Duration, ConnectionDate, ConnectionTime, Lang
$myarray = @(
    ('123',  'firstname',    'lastname', '127.0.0.1', 'lenovo',  '10:00',    '8/18/2019', '6:00 PM', 'Eng'),
    ('1',    'lastnam',      '',         '127.0.0.2', 'apple',   '2:30:00',  '8/18/2019', '1:00 AM', 'Chn'),
    ('86',   'user3',        '',         '127.0.0.1', 'dell',    '04:33',    '8/18/2019', '2:00 PM', ''),
    ('21',   'user4',        '',         '127.0.0.4', 'apple',   '30:00',    '8/17/2019', '1:00 PM', 'Eng')
)

# This is a generic for loop that prints the ComputerHostName, which is the 4th column.
# The 4th column is column #3 if counting from zero (0,1,2,3)
# I'm using a regular expression to match duration above 30 minutes with the '-match' operator
for ( $i = 0; $i -lt $myarray.Length; $i++ ) {
    if ( $myarray[$i][5] -match "[3-5][0-9]:[0-9][0-9]$" ){

        "$($myarray[$i][5]) - $($myarray[$i][3])"
    }
}
打印结果:

2:30:00 - 127.0.0.2
30:00 - 127.0.0.4

我想你有几个要求。我将描述一种使用通用的“for循环”和正则表达式实现的方法——您可以根据需要使用和调整它。有更好的方法可以做到这一点(Powershell快捷方式),但是根据您询问的方式,我假设理解是您的目标,因此如果您有任何编程语言的背景,那么这段代码应该很有用。希望这有帮助

# Here is your data formatted in an array.  Missing values are just empty fields.
# You could have fewer or more fields, but I've broken up your data into nine fields
# (0-8 when counting elements in an array)

# Customer ID, FName, LName, ComputerHostName, Brand, Duration, ConnectionDate, ConnectionTime, Lang
$myarray = @(
    ('123',  'firstname',    'lastname', '127.0.0.1', 'lenovo',  '10:00',    '8/18/2019', '6:00 PM', 'Eng'),
    ('1',    'lastnam',      '',         '127.0.0.2', 'apple',   '2:30:00',  '8/18/2019', '1:00 AM', 'Chn'),
    ('86',   'user3',        '',         '127.0.0.1', 'dell',    '04:33',    '8/18/2019', '2:00 PM', ''),
    ('21',   'user4',        '',         '127.0.0.4', 'apple',   '30:00',    '8/17/2019', '1:00 PM', 'Eng')
)

# This is a generic for loop that prints the ComputerHostName, which is the 4th column.
# The 4th column is column #3 if counting from zero (0,1,2,3)
# I'm using a regular expression to match duration above 30 minutes with the '-match' operator
for ( $i = 0; $i -lt $myarray.Length; $i++ ) {
    if ( $myarray[$i][5] -match "[3-5][0-9]:[0-9][0-9]$" ){

        "$($myarray[$i][5]) - $($myarray[$i][3])"
    }
}
打印结果:

2:30:00 - 127.0.0.2
30:00 - 127.0.0.4

如果显示的数据确实是固定宽度文件的输出,则需要尝试获取每个字段的宽度,以便对其进行解析。这里的一个障碍是原始标题名包含空格字符,我们需要用下划线替换它

为此,您可以使用以下功能:

function ConvertFrom-FixedWith {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string[]]$Content
    )

    $splitter   = '§¤¶'             # some unlikely string: Alt-21, [char]164, Alt-20  
    $needQuotes = '^\s+|[",]|\s+$'  # quote the fields if needed

    function _FWClean ([string]$field) {
        # internal helper function to clean a field value with regards to quoted fields
        $field = $_.Trim() -replace '(?<!\\)\\"|""', '§DQUOTE¶'
        if ($field -match '^"(.*)"$')  { $field = $matches[1] }
        if ($field -match $needQuotes) { $field = '"{0}"' -f $field }
        return $field -replace '§DQUOTE¶', '""'
    }

    # try and calculate the field widths using the first header line
    # this only works if none of the header names have spaces in them
    # and where the headers are separated by at least one space character.

    Write-Verbose "Calculating column widths using first row"
    $row = ($Content[0] -replace '\s+', ' ').Trim()
    $fields = @($row -split ' ' ) # | ForEach-Object { _FWClean $_ })
    $ColumnBreaks = for ($i = 1; $i -lt $fields.Length; $i++) {
        $Content[0].IndexOf($fields[$i]) 
    }
    $ColumnBreaks = $ColumnBreaks | Sort-Object -Descending

    Write-Verbose "Splitting fields and generating output"
    $Content | ForEach-Object {
        if ($null -ne $_ -and $_ -match '\S') {
            $line = $_
            # make sure lines that are too short get padded on the right
            if ($line.Length -le $ColumnBreaks[0]) { $line = $line.PadRight(($ColumnBreaks[0] + 1), ' ') }
            # add the splitter string on every column break point
            $ColumnBreaks | ForEach-Object { 
                $line = $line.Insert($_, $splitter)
            }
            # split on the splitter string, trim, and dedupe possible quotes
            # then join using the delimiter character
            @($line -split $splitter | ForEach-Object { _FWClean $_ }) -join ','
        }
    } | ConvertFrom-Csv    # the result is an array of PSCustomObjects
}
function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).Customer_ID
输出(屏幕上)

如果您的输入$text已经是一个字符串数组,存储了我们在您的问题中看到的所有INE,那么请省略
-split'\r?\n'


解析PsCustomObjects表的输入后,您可以通过另一个小助手功能获得连接30分钟或更长时间的客户:

function ConvertFrom-FixedWith {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string[]]$Content
    )

    $splitter   = '§¤¶'             # some unlikely string: Alt-21, [char]164, Alt-20  
    $needQuotes = '^\s+|[",]|\s+$'  # quote the fields if needed

    function _FWClean ([string]$field) {
        # internal helper function to clean a field value with regards to quoted fields
        $field = $_.Trim() -replace '(?<!\\)\\"|""', '§DQUOTE¶'
        if ($field -match '^"(.*)"$')  { $field = $matches[1] }
        if ($field -match $needQuotes) { $field = '"{0}"' -f $field }
        return $field -replace '§DQUOTE¶', '""'
    }

    # try and calculate the field widths using the first header line
    # this only works if none of the header names have spaces in them
    # and where the headers are separated by at least one space character.

    Write-Verbose "Calculating column widths using first row"
    $row = ($Content[0] -replace '\s+', ' ').Trim()
    $fields = @($row -split ' ' ) # | ForEach-Object { _FWClean $_ })
    $ColumnBreaks = for ($i = 1; $i -lt $fields.Length; $i++) {
        $Content[0].IndexOf($fields[$i]) 
    }
    $ColumnBreaks = $ColumnBreaks | Sort-Object -Descending

    Write-Verbose "Splitting fields and generating output"
    $Content | ForEach-Object {
        if ($null -ne $_ -and $_ -match '\S') {
            $line = $_
            # make sure lines that are too short get padded on the right
            if ($line.Length -le $ColumnBreaks[0]) { $line = $line.PadRight(($ColumnBreaks[0] + 1), ' ') }
            # add the splitter string on every column break point
            $ColumnBreaks | ForEach-Object { 
                $line = $line.Insert($_, $splitter)
            }
            # split on the splitter string, trim, and dedupe possible quotes
            # then join using the delimiter character
            @($line -split $splitter | ForEach-Object { _FWClean $_ }) -join ','
        }
    } | ConvertFrom-Csv    # the result is an array of PSCustomObjects
}
function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).Customer_ID
这将输出


更新


现在我们终于知道数据来自以制表符分隔的CSV文件,您不需要使用
convertfromfixedwith
函数

如果数据来自文件,只需使用

$table = Import-Csv -Path 'D:\customers.csv' -Delimiter "`t"
,如果它作为字符串或字符串数组来自另一个命令的输出:

$table = $original_output | ConvertFrom-Csv -Delimiter "`t"
然后,使用如上所述的“获取持续时间分钟”帮助功能获取连接时间超过30分钟的客户ID:

function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).'Customer ID'

如果显示的数据确实是固定宽度文件的输出,则需要尝试获取每个字段的宽度,以便对其进行解析。这里的一个障碍是原始标题名包含空格字符,我们需要用下划线替换它

为此,您可以使用以下功能:

function ConvertFrom-FixedWith {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string[]]$Content
    )

    $splitter   = '§¤¶'             # some unlikely string: Alt-21, [char]164, Alt-20  
    $needQuotes = '^\s+|[",]|\s+$'  # quote the fields if needed

    function _FWClean ([string]$field) {
        # internal helper function to clean a field value with regards to quoted fields
        $field = $_.Trim() -replace '(?<!\\)\\"|""', '§DQUOTE¶'
        if ($field -match '^"(.*)"$')  { $field = $matches[1] }
        if ($field -match $needQuotes) { $field = '"{0}"' -f $field }
        return $field -replace '§DQUOTE¶', '""'
    }

    # try and calculate the field widths using the first header line
    # this only works if none of the header names have spaces in them
    # and where the headers are separated by at least one space character.

    Write-Verbose "Calculating column widths using first row"
    $row = ($Content[0] -replace '\s+', ' ').Trim()
    $fields = @($row -split ' ' ) # | ForEach-Object { _FWClean $_ })
    $ColumnBreaks = for ($i = 1; $i -lt $fields.Length; $i++) {
        $Content[0].IndexOf($fields[$i]) 
    }
    $ColumnBreaks = $ColumnBreaks | Sort-Object -Descending

    Write-Verbose "Splitting fields and generating output"
    $Content | ForEach-Object {
        if ($null -ne $_ -and $_ -match '\S') {
            $line = $_
            # make sure lines that are too short get padded on the right
            if ($line.Length -le $ColumnBreaks[0]) { $line = $line.PadRight(($ColumnBreaks[0] + 1), ' ') }
            # add the splitter string on every column break point
            $ColumnBreaks | ForEach-Object { 
                $line = $line.Insert($_, $splitter)
            }
            # split on the splitter string, trim, and dedupe possible quotes
            # then join using the delimiter character
            @($line -split $splitter | ForEach-Object { _FWClean $_ }) -join ','
        }
    } | ConvertFrom-Csv    # the result is an array of PSCustomObjects
}
function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).Customer_ID
输出(屏幕上)

如果您的输入$text已经是一个字符串数组,存储了我们在您的问题中看到的所有INE,那么请省略
-split'\r?\n'


解析PsCustomObjects表的输入后,您可以通过另一个小助手功能获得连接30分钟或更长时间的客户:

function ConvertFrom-FixedWith {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string[]]$Content
    )

    $splitter   = '§¤¶'             # some unlikely string: Alt-21, [char]164, Alt-20  
    $needQuotes = '^\s+|[",]|\s+$'  # quote the fields if needed

    function _FWClean ([string]$field) {
        # internal helper function to clean a field value with regards to quoted fields
        $field = $_.Trim() -replace '(?<!\\)\\"|""', '§DQUOTE¶'
        if ($field -match '^"(.*)"$')  { $field = $matches[1] }
        if ($field -match $needQuotes) { $field = '"{0}"' -f $field }
        return $field -replace '§DQUOTE¶', '""'
    }

    # try and calculate the field widths using the first header line
    # this only works if none of the header names have spaces in them
    # and where the headers are separated by at least one space character.

    Write-Verbose "Calculating column widths using first row"
    $row = ($Content[0] -replace '\s+', ' ').Trim()
    $fields = @($row -split ' ' ) # | ForEach-Object { _FWClean $_ })
    $ColumnBreaks = for ($i = 1; $i -lt $fields.Length; $i++) {
        $Content[0].IndexOf($fields[$i]) 
    }
    $ColumnBreaks = $ColumnBreaks | Sort-Object -Descending

    Write-Verbose "Splitting fields and generating output"
    $Content | ForEach-Object {
        if ($null -ne $_ -and $_ -match '\S') {
            $line = $_
            # make sure lines that are too short get padded on the right
            if ($line.Length -le $ColumnBreaks[0]) { $line = $line.PadRight(($ColumnBreaks[0] + 1), ' ') }
            # add the splitter string on every column break point
            $ColumnBreaks | ForEach-Object { 
                $line = $line.Insert($_, $splitter)
            }
            # split on the splitter string, trim, and dedupe possible quotes
            # then join using the delimiter character
            @($line -split $splitter | ForEach-Object { _FWClean $_ }) -join ','
        }
    } | ConvertFrom-Csv    # the result is an array of PSCustomObjects
}
function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).Customer_ID
这将输出


更新


现在我们终于知道数据来自以制表符分隔的CSV文件,您不需要使用
convertfromfixedwith
函数

如果数据来自文件,只需使用

$table = Import-Csv -Path 'D:\customers.csv' -Delimiter "`t"
,如果它作为字符串或字符串数组来自另一个命令的输出:

$table = $original_output | ConvertFrom-Csv -Delimiter "`t"
然后,使用如上所述的“获取持续时间分钟”帮助功能获取连接时间超过30分钟的客户ID:

function Get-DurationInMinutes ([string]$Duration) {
    $h, $m, $s = (('0:{0}' -f $Duration) -split ':' | Select-Object -Last 3)
    return [int]$h * 60 + [int]$m
}

($table | Where-Object { (Get-DurationInMinutes $_.Duration) -ge 30 }).'Customer ID'

嗯。我很惊讶没有一个标准的方法可以做到这一点。基于

输出:

PS /Users/js/foo> ./columns | ft

Customer ID Client Name Computer Name Computer Brand Duration Connection Time   Lan
----------- ----------- ------------- -------------- -------- ---------------   ---
123         first last  127.0.0.1     lenovo         10:00    8/18/2019 6:00 PM Eng
1           lastname    127.0.0.2     apple          2:30:00  8/18/2019 1:00 AM Chn
86          user3       127.0.0.1     dell                    8/18/2019 2:00 PM 
21          user4       127.0.0.4     apple          30:00    8/17/2019 1:00 PM Eng

嗯。我很惊讶没有一个标准的方法可以做到这一点。基于

输出:

PS /Users/js/foo> ./columns | ft

Customer ID Client Name Computer Name Computer Brand Duration Connection Time   Lan
----------- ----------- ------------- -------------- -------- ---------------   ---
123         first last  127.0.0.1     lenovo         10:00    8/18/2019 6:00 PM Eng
1           lastname    127.0.0.2     apple          2:30:00  8/18/2019 1:00 AM Chn
86          user3       127.0.0.1     dell                    8/18/2019 2:00 PM 
21          user4       127.0.0.4     apple          30:00    8/17/2019 1:00 PM Eng

是您的输入还是您所需的输出?你提供的链接也回答了你关于过滤的问题。你的问题是什么?请告诉我们你的阵列是什么样子的。您正在向我们显示一些输出,但从中我们无法判断原始数组是一个对象数组,还是字段之间有空格和/或制表符的文本行。@vrdse我已编辑并显示了所需的输出。@Theo我已编辑以获得更好的视图。我的问题与我共享的链接相同,唯一的区别是我无法用它创建表。还有很多我没有展示的文件。看起来确实好多了,但是。。这似乎不是数组,只是数组或表的一些文本输出。我们需要知道是什么分隔了字段,特别是因为有些字段是空的。在您的示例中,空格都是空格字符,因此对我来说,这看起来像一个固定宽度的文本文件。这里是这样吗?是您输入的还是您所需的输出?你提供的链接也回答了你关于过滤的问题。你的问题是什么?请告诉我们你的阵列是什么样子的。您正在向我们显示一些输出,但从中我们无法判断原始数组是一个对象数组,还是字段之间有空格和/或制表符的文本行。@vrdse我已编辑并显示了所需的输出。@Theo我已编辑以获得更好的视图。我的问题与我共享的链接相同,唯一的区别是我无法用它创建表。还有很多我没有展示的文件。看起来确实好多了,但是。。这似乎不是数组,只是数组或表的一些文本输出。我们需要知道是什么分隔了字段,特别是因为有些字段是空的。在您的示例中,空格都是空格字符,因此对我来说,这看起来像一个固定宽度的文本文件。这里是这样吗?虽然我的输出宽度不同,但我会尝试一下。也许这会解决我面临的问题。我将在上更新输出