是否可以在 PowerShell 中截断字符串(使用
SubString()
?)到给定的最大字符数,甚至(如果原始字符串已经更短)?
例如:
foreach ($str in "hello", "good morning", "hi") { $str.subString(0, 4) }
截断适用于
hello
和 good morning
,但我收到 hi
的错误。
我想要以下结果:
hell
good
hi
您需要评估当前项目并获取其长度。如果长度小于 4,则在子字符串函数中使用它。
foreach ($str in "hello", "good morning", "hi") {
$str.subString(0, [System.Math]::Min(4, $str.Length))
}
或者您可以使用 PowerShell 的三元运算符替代方案来保持简单:
foreach ($str in "hello", "good morning", "hi") {
$(if ($str.length -gt 4) { $str.substring(0, 4) } else { $str })
}
虽然所有其他答案都是“正确的”,但它们的效率从次优变成了潜在的可怕。以下内容并不是对其他答案的批评,而是旨在对其基本操作进行指导性比较。毕竟,脚本编写更多的是让它尽快运行,而不是让它快速运行。
按顺序:
foreach ($str in "hello", "good morning", "hi") {
$str.subString(0, [System.Math]::Min(4, $str.Length))
}
这与我的产品基本相同,只是我们调用 substring 并告诉它返回整个字符串,而不是在 $str 太短时返回它。因此,次优。它仍在执行 if..then..else,但就在 Min 内,vis.
if (4 -lt $str.length) {4} else {$str.length}
foreach ($str in "hello", "good morning", "hi") { $str -replace '(.{4}).+','$1' }
使用正则表达式匹配抓取前四个字符,然后用它们替换整个字符串意味着整个(可能很长)字符串必须由未知复杂度/效率的匹配引擎扫描。
虽然人们可以看到“.+”只是匹配字符串的整个剩余部分,但匹配引擎可能会构建一个大的回溯替代列表,因为模式没有锚定(开头没有 ^)。这里巧妙的一点(未描述)是,如果字符串少于五个字符(四次
.
,后跟一个或多个.
),则整个匹配失败,替换返回未更改的 $str。
foreach ($str in "hello", "good morning", "hi") {
try {
$str.subString(0, 4)
}
catch [ArgumentOutOfRangeException] {
$str
}
}
故意抛出异常而不是编程边界检查是一个有趣的解决方案,但谁知道当异常从 try 块冒泡到 catch 时会发生什么。在这个简单的情况下可能不多,但它不会是推荐的一般做法,除非存在许多可能的错误源(使得检查所有错误源变得很麻烦),但只有几个响应。
有趣的是,在其他地方使用
-join
和数组切片回答类似问题(这不会导致索引超出范围的错误,只是忽略丢失的元素):
$str[0..3] -join "" # Infix
(或更简单)
-join $str[0..3] # Prefix
鉴于 string
和
char[]
的存储之间的高度相似性,可能是最有效的(经过适当的优化)。需要优化,因为默认情况下, $str[0..3] 是一个 object[],每个元素都是一个字符,因此与字符串(在内存中)几乎没有相似之处。给 PowerShell 一点提示可能会有用,
-join [char[]]$str[0..3]
但是,也许只是告诉它你真正想要的,
new-object string (,$str[0..3]) # Need $str[0..3] to be a member of an array of constructor arguments
从而直接调用
new String(char[])
最好了。
你可以捕获异常:
foreach ($str in "hello", "good morning", "hi") {
try {
$str.subString(0, 4)
}
catch [ArgumentOutOfRangeException] {
$str
}
}
更多正则表达式的爱,使用lookbehind:
PS > 'hello','good morning','hi' -replace '(?<=(.{4})).+'
hell
good
hi
我一如既往地参加聚会迟到了!我已经使用 PadRight 字符串函数来解决这样的问题。与其他建议相比,我无法评论其相对效率:
foreach ($str in "hello", "good morning", "hi") { $str.PadRight(4, " ").SubString(0, 4) }
您还可以使用
-replace
foreach ($str in "hello", "good morning", "hi") { $str -replace '(.{4}).+','$1' }
hell
good
hi
旧线程,但我遇到了同样的问题并最终得到以下结果:-
$str.padright(4,"✓").substring(0,4).replace("✓","")
将 ✓ 字符替换为您想要的任何流氓角色。我使用了按键盘上的 ALT GR 和反引号键获得的字符。
呃,我觉得很脏,但它是:
-join ("123123123".ToCharArray() | select -first 42)
输出完整字符串:123123123
-join ("123123123".ToCharArray() | select -first 3)
输出前 3 个字符:123
更简单,还是脏!
-join "123123123"[0..3]
(记住,它是从零开始的,所以有4个字符,相应调整)