PowerShell 从 csv 文件中读取列值

PowerShell read column value from csv file

这是我下面的 CSV 格式输入数据,角色、管理员、会计和安全是列。

roles, admin,accountant,security
Engineer,  ,x , ,

我想使用具有以下代码的列获取行的值,例如,foreach 会计列应该 return 'x',但我得到了其他东西。

$path = "$PSScriptRoot\Test.csv"
$csv = Import-Csv -path $path -Delimiter ","
$columns = $csv | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'

$csv | ForEach-Object {

$row = $_
foreach ($col in $columns) {

   Write-Host " vaalue of scripting is : $col " 
   Write-Host " vaalue of scripting row is : $row.$col " 
   Start-Sleep -s 10

}

}

我得到的输出是

 vaalue of scripting is : accountant 
 vaalue of scripting row is : @{roles=Engineer; admin=; accountant=x ; security=}.accountant 
 vaalue of scripting is : admin 
 vaalue of scripting row is : @{roles=Engineer; admin=; accountant=x ; security=}.admin
 vaalue of scripting is : roles 
 vaalue of scripting row is : @{roles=Engineer; admin=; accountant=x ; security=}.roles

如何使用

获得会计列或任何其他列值的 'x'

根据我的评论,简短的回答是使用 Subexpression operator $( ),这将允许 PowerShell 引用 属性 $col 对象 $row.

MS 文档的简短摘录:

Use this when you want to use an expression within another expression. For example, to embed the results of command in a string expression.


为了给你一个简短的解释为什么需要这个,以此为例:

$object = [pscustomobject]@{
    foo = 'var'
}

$property = 'foo'

当我们做"$object.$property"或者简单来说,"$object.foo",双引号"..." 不允许 PowerShell 从 $object 引用 foo 属性 因为 dot . 被解释为文字而不是点方法。此外,引号将 $object 转换为其 字符串化 ? 表示形式 @{foo=var} 后跟文字点 . 后跟 $property.

的变量展开

about_Properties 的另一个摘录:

The most common way to get the values of the properties of an object is to use the dot method. Type a reference to the object, such as a variable that contains the object, or a command that gets the object. Then, type a dot (.) followed by the property name.


最后,除了 $(...) 之外,我们还有什么其他选择可以解决这个问题 :

'Value of $object.$property is "{0}".' -f $object.$property
[string]::Format('Value of $object.$property is "{0}".', $object.$property)
  • 使用+连接字符串也是一个非常有名的方法:
'Value of $object.$property is "' + $object.$property + '".'

作为旁注,与实际问题无关,这可能是更 直接 处理您的代码的方式:

@'
roles,admin,accountant,security
Engineer,,x,,
Operator,,y,,
'@ |
ConvertFrom-Csv | ForEach-Object -Begin { $i = 1 } -Process {
    foreach($Property in $_.PSObject.Properties.Name)
    {
        
        'Value of Row {0} Column "{1}" is "{2}"' -f 
            $i, $Property, (
                'NULL', ($val = $_.$Property)
            )[[int][bool]$val]
    }
    $i++
}

注意 .PSObject to access the object's properties and methods, an alternative to Get-Member.

的使用

以上将导致:

Value of Row 1 Column "roles" is "Engineer"
Value of Row 1 Column "admin" is "NULL"
Value of Row 1 Column "accountant" is "x"
Value of Row 1 Column "security" is "NULL"
Value of Row 2 Column "roles" is "Operator"
Value of Row 2 Column "admin" is "NULL"
Value of Row 2 Column "accountant" is "y"
Value of Row 2 Column "security" is "NULL"

我是根据你的 csv 文件写的,如果有效请告诉我(更改文件夹路径和文件名)。

$folderspath = 'C:\Test'
$csvfilename = 'info.csv'
$csvfilepath = $folderspath + "\" + $csvfilename
$csvfilepath = $csvfilepath.ToString()

$csvfile = Import-CSV -Path $csvfilepath -Delimiter ","
    ForEach ($row in $csvfile) {
        IF($row.security -eq "High") {
            $Roles = $row.roles
            $Admin = $row."admin"
            $Accountant = $row.accountant
            $Security = $row."security"

            Write-Host "Roles: " $Roles "; Admin:" $Admin "; Accountant:" $Accountant "; ` 
            Security:" $Security
    }
}

我用的csv文件

roles, admin,accountant,security
Engineer,  ,x , ,
Engineer2,Yes ,x ,High,
Engineer3, No, , Low,