I have a Cloud Foundry CLI command, cf apps
, that outputs:
name requested state processes routes
appname_1 started web:2/2 route1.com
appname_2 started web:1/1 route2.com
How do I access all name
column values, and then loop over them?
The idea is to get the list of all app names and run the cf delete <app_name>
so that I can avoid the hassle of having to delete the apps one by one.
I tried the following script earlier
Fetch apps
$apps = cf apps | Where-Object {
$_ -match 'appname'
} | % { $_.Trim() } | ConvertFrom-String -PropertyNames 'Name','Value'
And then use for-loop to delete the apps using cf delete <appname> -f
command
for ($i = 0; $i -lt $apps.Length; $i++) {
$char = $apps.Name[$i]
cf delete $char -f
}
Preface:
The solution below uses text parsing to convert the tabular text output to objects, reflecting all the fields in the table, not just name
.
A simpler solution that extracts the name
fields only is:
$names =
cf apps |
select -Skip 1 |
foreach { ($_ -split ' ', 2)[0] }
Such an approach is best avoided, but cannot always be, namely if the source CLI lacks support for outputting a structured text format, such as JSON or CSV; indeed that seems to be the case for the CloudFoundry cf
, as of this writing.
Use the following, which makes the following assumptions, which are consistent with your sample data:
# Initialize helper variables.
$propNames = $null
$ohtTemplate = [ordered] @{}
# Parse the tabular CLI output into objects.
$appInfos =
cf apps |
ForEach-Object {
$fields = ($_ -split ' {2,}').Trim()
if ($null -eq $propNames) {
$propNames = $fields
foreach ($propName in $propNames) {
$ohtTemplate[$propName] = $null
}
return
}
foreach ($i in 0..($propNames.Count-1)) {
if ($i -lt $fields.Count) {
$ohtTemplate[$propNames[$i]] = $fields[$i]
}
else {
$ohtTemplate[$propNames[$i]] = $null
}
}
[pscustomobject] $ohtTemplate
}
# Output the resulting objects, for visual inspection.
$appInfos
The above emits custom objects whose property names correspond to the table header, and whose values contain a row's column values (which are all stored as strings).
PowerShell's for-display output-formatting system conveniently renders the resulting objects as follows:
name requested state processes routes
---- --------------- --------- ------
appname_1 started web:2/2 route1.com
appname_2 started web:1/1 route2.com
To get just the names, for instance, as an array, using member-access enumeration, use $appInfos.name
:
# Output from `$appInfos.name`
appname_1
appname_2
To get just the first app's name, use $appInfos[0].name
.
Of course, you can use $appInfos | ForEach-Object { <# work with $_ #> }
, foreach ($app in $appInfos) { <# work with $app #> }
or $appInfos.ForEach({ <# work with $_ #> })
, as usual, to iterate over all app infos.