PowerShell中的子串以截断字符串长度

Jér*_*ôme 9 string powershell substring

在PowerShell中,是否可以将字符串(使用SubString()?)截断为给定的最大字符数,即使原始字符串已经更短

例如:

foreach ($str in "hello", "good morning", "hi") { $str.subString(0, 4) }
Run Code Online (Sandbox Code Playgroud)

截断正在为hellogood morning,但我得到了一个错误hi.

我想得到以下结果:

hell
good
hi
Run Code Online (Sandbox Code Playgroud)

Edu*_*Uta 19

您需要评估当前项目并获取其长度.如果长度小于4,则在子字符串函数中使用它.

foreach ($str in "hello", "good morning", "hi") {
    $str.subString(0, [System.Math]::Min(4, $str.Length)) 
}
Run Code Online (Sandbox Code Playgroud)


小智 10

或者你可以保持简单,使用PowerShell替代三元运算符:

foreach ($str in "hello", "good morning", "hi") {
  $(if ($str.length -gt 4) { $str.substring(0, 4) } else { $str })
}
Run Code Online (Sandbox Code Playgroud)

虽然所有其他答案都是"正确的",但它们的效率从次优到可能是可怕的.以下不是对其他答案的批评,而是旨在作为对其基本操作的指导性比较.毕竟,脚本编写更多的是让它快速运行而不是让它快速运行.

为了:

  1.  

    foreach ($str in "hello", "good morning", "hi") {
        $str.subString(0, [System.Math]::Min(4, $str.Length))
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这与我的产品基本相同,只是当它太短时,我们调用substring并告诉它返回整个字符串,而不仅仅返回$ str.因此,次优.它仍在做if..then..else但只是在Min,vis内.

    if (4 -lt $str.length) {4} else {$str.length}
    
    Run Code Online (Sandbox Code Playgroud)
  2.  

    foreach ($str in "hello", "good morning", "hi") { $str -replace '(.{4}).+','$1' }
    
    Run Code Online (Sandbox Code Playgroud)

    使用正则表达式匹配来获取前四个字符,然后用它们替换整个字符串意味着整个(可能很长)字符串必须由未知复杂性/效率的匹配引擎扫描.

    虽然一个人可以看到'.+'只是匹配字符串的整个剩余部分,但匹配引擎可能会构建一个大的回溯备选列表,因为模式没有锚定(在开头没有^).这里(未描述)聪明的一点是,如果字符串少于五个字符(四次.后跟一个或多个.),则整个匹配失败并且replace返回$ str unaltered.

  3.  

    foreach ($str in "hello", "good morning", "hi") {
      try {
        $str.subString(0, 4)
      }
      catch [ArgumentOutOfRangeException] {
        $str
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    故意抛出异常而不是编程边界检查是一个有趣的解决方案,但谁知道发生了什么,因为异常从try块冒出来到catch.在这个简单的情况下可能并不多,但除了在存在许多可能的错误来源(使检查所有错误很麻烦)的情况下,它不会是推荐的通用做法,而只是少数响应.

有趣的是,对其他地方使用-join和数组切片的类似问题的答案(不会导致索引上的错误超出范围,只是忽略缺少的元素):

$str[0..3] -join ""   # Infix
Run Code Online (Sandbox Code Playgroud)

(或更简单地说)

-join $str[0..3]      # Prefix
Run Code Online (Sandbox Code Playgroud)

鉴于存储string和存储之间的强烈相似性,它可能是最有效的(通过适当的优化)char[].优化是必需的,因为默认情况下,$ str [0..3]是一个object [],每个元素都是一个char,因此与字符串(在内存中)几乎没有相似之处.给PowerShell一点提示可能很有用,

-join [char[]]$str[0..3]
Run Code Online (Sandbox Code Playgroud)

但是,也许只是告诉它你真正想要的是什么,

new-object string (,$str[0..3]) # Need $str[0..3] to be a member of an array of constructor arguments
Run Code Online (Sandbox Code Playgroud)

从而直接调用

new String(char[])
Run Code Online (Sandbox Code Playgroud)

是最好的.