I have the following string
$list = @("123","456","789")
$template = "https://mysite.test/api/v1/policy/{id}/version/{id}/example"
I am working on a function to meet the following requirements :
{id}
in the order provided by an array ($list
){id}
append the last id
at the end of the $string
(in this example, array contains 3 items, string will be appended by /789
)$ids
but fails if array list does not match list of {id}
or list of array +1 (for the above append scenario)The issue is that every {id} is replaced by the first item from my list, as shown below
if ($template.Contains('{id}')) {
foreach ($id in $list ) {
$template = $template -replace '{id}', $id
}
}
$string
https://mysite.test/api/v1/policy/123/version/123/example
Expected values
array with 2 values
https://mysite.test/api/v1/policy/123/version/456/example
array with 3 values
https://mysite.test/api/v1/policy/123/version/456/example/789
The easiest option is to use format string instead of {id}
for interpolating the values:
$template = 'https://mysite.test/api/v1/policy/{0}/version/{1}/example{2}'
$list = @('123', '456', '789')
if ($list.Count -lt 3) {
$list += $null
}
else {
$list[2] = '/' + $list[2] # prepend `/` to the last item
}
$template -f $list
If you must use {id}
then, perhaps using regex replacement with a match evaluator or replacement with a scriptblock work for this use case. Basically, in the evaluator you can increment an index for each pattern match and get the next replacement value in $list
.
It would look something like this for PowerShell 5.1:
$template = 'https://mysite.test/api/v1/policy/{id}/version/{id}/example'
$list = @('123', '456', '789')
$idx = @(0)
[regex]::Replace($template, '{id}|$', {
# if there is a "next value" in the list
if ($next = $list[$idx[0]++]) {
# if matching EOL
if (-not $args[0].Value) {
return '/' + $next
}
# else
$next
}
})
And like this for PowerShell 7+:
$template = 'https://mysite.test/api/v1/policy/{id}/version/{id}/example'
$list = @('123', '456', '789')
$idx = @(0)
$template -replace '{id}|$', {
# if there is a "next value" in the list
if ($next = $list[$idx[0]++]) {
# if matching EOL
if (-not $_.Value) {
return '/' + $next
}
# else
$next
}
}