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

时间:2015-01-14 13:38:30

标签: string powershell substring

在PowerShell中,是否可以截断字符串(使用SubString()?)到给定的最大字符数,甚至如果原始字符串已经更短

例如:

foreach ($str in "hello", "good morning", "hi") { $str.subString(0, 4) }

截断适用于hellogood morning,但我收到了hi的错误。

我想要以下结果:

hell
good
hi

7 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:8)

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

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

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

按顺序:

  1. 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}
    
  2. foreach ($str in "hello", "good morning", "hi") { $str -replace '(.{4}).+','$1' }
    

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

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

  3. foreach ($str in "hello", "good morning", "hi") {
      try {
        $str.subString(0, 4)
      }
      catch [ArgumentOutOfRangeException] {
        $str
      }
    }
    

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

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

    $str[0..3] -join ""   # Infix
    

    (或更简单地说)

    -join $str[0..3]      # Prefix
    
    鉴于stringchar[]的存储之间存在很强的相似性,

    可能是最有效的(通过适当的优化)。优化是必需的,因为默认情况下,$ str [0..3]是一个object [],每个元素都是一个char,因此与字符串(在内存中)几乎没有相似之处。给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[])
    

    是最好的。

答案 2 :(得分:1)

您可以捕获异常:

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

答案 3 :(得分:1)

使用lookbehind,更喜欢正则表达式:

PS > 'hello','good morning','hi' -replace '(?<=(.{4})).+'
hell
good
hi

答案 4 :(得分:1)

我和往常一样迟到了!我已经使用 PadRight 字符串函数来解决这样的问题。与其他建议相比,我无法评论其相对效率:

foreach ($str in "hello", "good morning", "hi") { $str.PadRight(4, " ").SubString(0, 4) }

答案 5 :(得分:0)

您也可以使用-replace

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

hell
good
hi

答案 6 :(得分:0)

旧线程,但我遇到了同样的问题,结果如下:-

$str.padright(4,"✓").substring(0,4).replace("✓","")

用你想要的任何流氓角色替换 ✓ 角色。我使用了通过按键盘上的 ALT GR 和反引号键获得的字符。

相关问题