如何将一系列以连字符分隔的数字分别填充为两位数?
How can I pad a series of hyphen-separated numbers each to two digits?
我是 PowerShell 编程的新手,因此需要有关我拥有的字符串集的帮助,如下所述:
"14-2-1-1"
"14-2-1-1-1"
"14-2-1-1-10"
如果 1
和 9
之间的每个数字,我想用零填充 -
之间的数字。所以结果应该是这样的:
"14-02-01-01"
"14-02-01-01-01"
"14-02-01-01-10"
我想出了以下代码,但想知道是否有 better/faster 解决方案。
$Filenum = "14-2-1-1"
$hicount = ($Filenum.ToCharArray() | Where-Object{$_ -eq '-'} | Measure-Object).Count
$FileNPad = ''
For ($i=0; $i -le $hicount; $i++) {
$Filesec= "{$i}" -f $Filenum.split('-')
If ([int]$Filesec -le 9)
{
$FileNPad = "$FileNPad-"+"0"+"$Filesec"
}
Else
{
$FileNPad="$FileNPad-$Filesec"
}
}
$FileNPad = $FileNPad.Trim("-"," ")
与其尝试手动跟踪有多少元素并检查每个值,您可以简单地在 -
、padleft 上拆分,然后与 -
重新合并
"14-2-1-1","14-2-1-1-1","14-2-1-1-10" | ForEach-Object {
($_ -split '-').PadLeft(2,'0') -join '-'
}
输出
14-02-01-01
14-02-01-01-01
14-02-01-01-10
我倾向于使用 之类的东西,因为它很清晰,但这是另一种看待它的方式。下面的最后一节显示了一个解决方案,该解决方案可能与它自己的一些优点一样清晰。
输入中数字组的模式
您的输入字符串由一组或多组组成,其中每组...
- ...包含一位或多位数字,并且...
- ...前面是
-
或字符串的开头,并且...
- ...后跟
-
或字符串结尾。
需要插入前导 "0"
的组只包含一个数字;也就是说,它们包括...
- ...a
-
或字符串的开头,后跟...
- ...单个数字,后跟...
- ...a
-
或字符串结尾。
使用 -replace
运算符替换 single-digit 数字组
我们可以使用 regular expressions with the -replace
operator 来定位该模式并将单个数字替换为 "0"
后跟相同的数字...
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { $_ -replace '(?<=-|^)(\d)(?=-|$)', '0' }
...输出...
00-00-00-00
00-00-00-00
01-02-03-04
01-02-03-04
10-20-30-40
11-22-33-44
如文档所述,-replace
运算符的用法如下...
<input> -replace <regular-expression>, <substitute>
匹配模式
匹配模式 '(?<=-|^)(\d)(?=-|$)'
表示...
(?<=-|^)
:-
或字符串开头的 zero-width positive lookbehind assertion
- 换句话说,匹配但不捕获
-
或字符串的开头
(\d)
:单个digit, captured and made available with the replacement substitution</code></li>
<li><code>(?=-|$)
:-
或字符串末尾的 zero-width positive lookahead assertion
- 换句话说,匹配但不捕获
-
或字符串结尾
替换模式
替换模式'0'
意味着...
- 文字
'0'
,后跟...
- 第一次捕获的值(
(\d)
)
使用 [Regex]::Replace()
和替换 [String]
替换 single-digit 数字组
除了 -replace
运算符,您还可以调用 static
Replace()
method of the [Regex]
class...
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { [Regex]::Replace($_, '(?<=-|^)(\d)(?=-|$)', '0') }
...结果是一样的。
使用 [Regex]::Replace()
和 [MatchEvaluator]
替换数字组
正则表达式和 imperative solutions is to call an overload of the Replace()
method that takes a [MatchEvaluator]
的混合体,而不是替换 [String]
...
# This [ScriptBlock] will be passed to a [System.Text.RegularExpressions.MatchEvaluator] parameter
$matchEvaluator = {
# The [System.Text.RegularExpressions.Match] parameter
param($match)
# The replacement [String]
return $match.Value.PadLeft(2, '0')
}
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { [Regex]::Replace($_, '(\d+)', $matchEvaluator) }
这会产生与上面相同的结果。
A [MatchEvaluator]
is a delegate that takes a Match
to be replaced ($match
) and returns the [String]
with which to replace it (the matched text left-padded to two digits). Also note that, whereas above we are capturing only standalone digits (\d)
, here we capture all groups of one or more digits (\d+)
and leave it to PadLeft()
以确定是否需要前导 "0"
。
我认为这是一个比单独使用正则表达式更有吸引力的解决方案,因为它是最好的解决方案和 imperative 世界:
- 它使用简单的正则表达式模式来定位输入字符串中的数字组
- 它使用一个简单的
[ScriptBlock]
来转换输入字符串中的数字组
- 通过不拆分输入字符串,它不会创建尽可能多的中间字符串和数组 garbage
- 这种潜在的性能改进是否完全被使用正则表达式所掩盖,我不能说没有基准测试
我是 PowerShell 编程的新手,因此需要有关我拥有的字符串集的帮助,如下所述:
"14-2-1-1"
"14-2-1-1-1"
"14-2-1-1-10"
如果 1
和 9
之间的每个数字,我想用零填充 -
之间的数字。所以结果应该是这样的:
"14-02-01-01"
"14-02-01-01-01"
"14-02-01-01-10"
我想出了以下代码,但想知道是否有 better/faster 解决方案。
$Filenum = "14-2-1-1"
$hicount = ($Filenum.ToCharArray() | Where-Object{$_ -eq '-'} | Measure-Object).Count
$FileNPad = ''
For ($i=0; $i -le $hicount; $i++) {
$Filesec= "{$i}" -f $Filenum.split('-')
If ([int]$Filesec -le 9)
{
$FileNPad = "$FileNPad-"+"0"+"$Filesec"
}
Else
{
$FileNPad="$FileNPad-$Filesec"
}
}
$FileNPad = $FileNPad.Trim("-"," ")
与其尝试手动跟踪有多少元素并检查每个值,您可以简单地在 -
、padleft 上拆分,然后与 -
"14-2-1-1","14-2-1-1-1","14-2-1-1-10" | ForEach-Object {
($_ -split '-').PadLeft(2,'0') -join '-'
}
输出
14-02-01-01
14-02-01-01-01
14-02-01-01-10
我倾向于使用
输入中数字组的模式
您的输入字符串由一组或多组组成,其中每组...
- ...包含一位或多位数字,并且...
- ...前面是
-
或字符串的开头,并且... - ...后跟
-
或字符串结尾。
需要插入前导 "0"
的组只包含一个数字;也就是说,它们包括...
- ...a
-
或字符串的开头,后跟... - ...单个数字,后跟...
- ...a
-
或字符串结尾。
使用 -replace
运算符替换 single-digit 数字组
我们可以使用 regular expressions with the -replace
operator 来定位该模式并将单个数字替换为 "0"
后跟相同的数字...
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { $_ -replace '(?<=-|^)(\d)(?=-|$)', '0' }
...输出...
00-00-00-00
00-00-00-00
01-02-03-04
01-02-03-04
10-20-30-40
11-22-33-44
如文档所述,-replace
运算符的用法如下...
<input> -replace <regular-expression>, <substitute>
匹配模式
匹配模式 '(?<=-|^)(\d)(?=-|$)'
表示...
(?<=-|^)
:-
或字符串开头的 zero-width positive lookbehind assertion- 换句话说,匹配但不捕获
-
或字符串的开头
- 换句话说,匹配但不捕获
(\d)
:单个digit, captured and made available with the replacement substitution</code></li> <li><code>(?=-|$)
:-
或字符串末尾的 zero-width positive lookahead assertion- 换句话说,匹配但不捕获
-
或字符串结尾
- 换句话说,匹配但不捕获
替换模式
替换模式'0'
意味着...
- 文字
'0'
,后跟... - 第一次捕获的值(
(\d)
)
使用 [Regex]::Replace()
和替换 [String]
替换 single-digit 数字组
除了 -replace
运算符,您还可以调用 static
Replace()
method of the [Regex]
class...
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { [Regex]::Replace($_, '(?<=-|^)(\d)(?=-|$)', '0') }
...结果是一样的。
使用 [Regex]::Replace()
和 [MatchEvaluator]
替换数字组
正则表达式和 imperative solutions is to call an overload of the Replace()
method that takes a [MatchEvaluator]
的混合体,而不是替换 [String]
...
# This [ScriptBlock] will be passed to a [System.Text.RegularExpressions.MatchEvaluator] parameter
$matchEvaluator = {
# The [System.Text.RegularExpressions.Match] parameter
param($match)
# The replacement [String]
return $match.Value.PadLeft(2, '0')
}
'0-0-0-0', '00-00-00-00', '1-2-3-4', '01-02-03-04', '10-20-30-40', '11-22-33-44' |
ForEach-Object -Process { [Regex]::Replace($_, '(\d+)', $matchEvaluator) }
这会产生与上面相同的结果。
A [MatchEvaluator]
is a delegate that takes a Match
to be replaced ($match
) and returns the [String]
with which to replace it (the matched text left-padded to two digits). Also note that, whereas above we are capturing only standalone digits (\d)
, here we capture all groups of one or more digits (\d+)
and leave it to PadLeft()
以确定是否需要前导 "0"
。
我认为这是一个比单独使用正则表达式更有吸引力的解决方案,因为它是最好的解决方案和 imperative 世界:
- 它使用简单的正则表达式模式来定位输入字符串中的数字组
- 它使用一个简单的
[ScriptBlock]
来转换输入字符串中的数字组 - 通过不拆分输入字符串,它不会创建尽可能多的中间字符串和数组 garbage
- 这种潜在的性能改进是否完全被使用正则表达式所掩盖,我不能说没有基准测试