[英]How can I pad a series of hyphen-separated numbers each to two digits?
I am fairly new to PowerShell programming, so need help with set of strings I have as described below:我是 PowerShell 编程的新手,所以需要我的一组字符串的帮助,如下所述:
"14-2-1-1"
"14-2-1-1-1"
"14-2-1-1-10"
I want to pad zero to each number in between -
if that number is between 1
and 9
.我想将零填充到中间的每个数字
-
如果该数字介于1
和9
之间。 So the result should look like:所以结果应该是这样的:
"14-02-01-01"
"14-02-01-01-01"
"14-02-01-01-10"
I came up with the following code but was wondering if there is a better/faster solution.我想出了以下代码,但想知道是否有更好/更快的解决方案。
$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("-"," ")
Instead of trying to manually keep track of how many elements and inspect each value, you can simply split on -
, padleft, then join back together with -
无需尝试手动跟踪有多少元素并检查每个值,您可以简单地拆分
-
,padleft,然后重新加入-
"14-2-1-1","14-2-1-1-1","14-2-1-1-10" | ForEach-Object {
($_ -split '-').PadLeft(2,'0') -join '-'
}
Which outputs哪些输出
14-02-01-01
14-02-01-01-01
14-02-01-01-10
I'd be inclined to go with something like Doug Maurer's answer due to its clarity, but here's another way to look at this.由于它的清晰度,我倾向于 go 和类似Doug Maurer 的答案,但这是另一种看待这个问题的方式。 The last section below shows a solution that might be just as clear with some advantages of its own.
下面的最后一节显示了一个解决方案,该解决方案可能与它自己的一些优点一样清晰。
Your input strings are composed of one or more groups, where each group...您的输入字符串由一个或多个组组成,其中每个组...
-
or the beginning of the string, and... -
或字符串的开头,并且...-
or the end of the string. -
或字符串的末尾。 Groups that require a leading "0"
to be inserted contain exactly one digit;要求插入前导
"0"
的组恰好包含一个数字; that is, they consist of...也就是说,它们包括...
-
or the beginning of the string, followed by... -
或字符串的开头,后跟...-
or the end of the string. -
或字符串的末尾。-replace
operator-replace
运算符替换单个数字组We can use regular expressions with the -replace
operator to locate that pattern and replace the single digit with a "0"
followed by that same digit...我们可以使用带有
-replace
运算符的正则表达式来定位该模式,并将单个数字替换为"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$1' }
...which outputs... ...哪个输出...
00-00-00-00
00-00-00-00
01-02-03-04
01-02-03-04
10-20-30-40
11-22-33-44
As the documentation describes, the -replace
operator is used like this...如文档所述,
-replace
运算符的用法如下...
<input> -replace <regular-expression>, <substitute>
The match pattern '(?<=-|^)(\d)(?=-|$)'
means...匹配模式
'(?<=-|^)(\d)(?=-|$)'
意味着......
(?<=-|^)
: A zero-width positive lookbehind assertion for either -
or the beginning of the string (?<=-|^)
:对于-
或字符串开头的零宽度正回顾断言
-
or the beginning of the string-
或字符串的开头(\d)
: A single digit , captured and made available with the replacement substitution $1
(\d)
:单个数字, 捕获并通过替换$1
提供(?=-|$)
: A zero-width positive lookahead assertion for either -
or the end of the string (?=-|$)
:对于-
或字符串结尾的零宽度正先行断言
-
or the end of the string-
或字符串的末尾The replacement pattern '0$1'
means...替换模式
'0$1'
意味着......
'0'
, followed by...'0'
,后跟......(\d)
)(\d)
)[Regex]::Replace()
and a replacement [String]
[Regex]::Replace()
和替换[String]
替换单个数字组Instead of the -replace
operator you can also call the static
Replace()
method of the [Regex]
class ...除了
-replace
运算符,您还可以调用[Regex]
class的static
Replace()
方法...
'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$1') }
...and the result is the same. ...结果是一样的。
[Regex]::Replace()
and a [MatchEvaluator]
[Regex]::Replace()
和[MatchEvaluator]
替换数字组A hybrid of the regular expression and imperative solutions is to call an overload of the Replace()
method that takes a [MatchEvaluator]
instead of a replacement [String]
...正则表达式和命令式解决方案的混合体是调用
Replace()
方法的重载,该方法采用[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) }
This produces the same result as above.这会产生与上述相同的结果。
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). [MatchEvaluator]
是一个委托,它接受要替换的Match
( $match
) 并返回用于替换它的[String]
( 匹配的文本左填充到两位数)。 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()
to figure out if a leading "0"
is needed.另请注意,虽然上面我们只捕获独立数字
(\d)
,但在这里我们捕获所有一个或多个数字组(\d+)
并将其留给PadLeft()
来确定是否需要前导"0"
。
I think this is a much more compelling solution than regular expressions alone because it's the best of that and the imperative world:我认为这是一个比单独使用正则表达式更有说服力的解决方案,因为它是正则表达式和命令式世界中最好的:
[ScriptBlock]
to transform digit groups in the input string[ScriptBlock]
来转换输入字符串中的数字组
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.