首页 > 解决方案 > PowerShell将字符串切成两半

问题描述

我有由相同的一半组成的行,我想从中删除一半;例如,'AbcAbc'应该变成'Abc'.

数据总是看起来像:

10.22.20.106/tcp/8010.22.20.106/tcp/80
10.22.20.46/tcp/44310.22.20.46/tcp/443
10.22.20.90/tcp/44310.22.20.90/tcp/443
10.22.20.90/tcp/8010.22.20.90/tcp/80
10.22.20.89/tcp/44310.22.20.89/tcp/443
10.22.20.89/tcp/8010.22.20.89/tcp/80
10.22.20.29/tcp/44310.22.20.29/tcp/443
10.22.20.29/tcp/8010.22.20.29/tcp/80
10.22.20.122/tcp/44310.22.20.122/tcp/443
10.22.20.123/tcp/44310.22.20.123/tcp/443
10.22.20.79/tcp/44310.22.20.79/tcp/443
10.22.20.79/tcp/8010.22.20.79/tcp/80
10.22.20.78/tcp/44310.22.20.78/tcp/443
10.22.20.78/tcp/8010.22.20.78/tcp/80
10.22.20.74/tcp/44310.22.20.74/tcp/443
10.22.20.74/tcp/8010.22.20.74/tcp/80
10.22.20.22/tcp/44310.22.20.22/tcp/443
10.22.20.22/tcp/8010.22.20.22/tcp/80
10.22.20.99/tcp/44310.22.20.99/tcp/443
10.22.20.99/tcp/8010.22.20.99/tcp/80
10.22.20.54/tcp/44310.22.20.54/tcp/443
10.22.20.54/tcp/8010.22.20.54/tcp/80

我计算了字符串中的字符数,然后将其减半,但不确定如何使用计算出的(减半)字符数来剪切原始字符串。

$vip_ip = $vip_line.("Virtual IP Address/Protocol/Port")
$half_string = $vip_ip.length /2

$vip_ip.length 44

$half_string 22

$vip_cut = $vip_ip.(0,-$halfstring)

标签: regexpowershellsubstringbacktrackingbackreference

解决方案


马特的答案是要走的路,但只是提出一个基于正则表达式的替代方案
-replace,主要是作为一个有趣的实验

注意:虽然这个解决方案很简洁,但在我的测试中它是模糊的,并且比.Substring()基于 - 的方法慢 2-3 倍。

# Extract one half of the input string consisting of identical halves.
PS> '10.22.20.54/tcp/44310.22.20.54/tcp/443' -replace '^(.+)\1$', '$1'
10.22.20.54/tcp/443
  • 正则表达式子表达式匹配字符串开头 ( ) 处的^(.+)一个或多个 ( +)(非换行符)字符 ( ),并在捕获组中捕获它们。.^(...)

  • \1$匹配一个反向引用( ),它指的是(第一个也是唯一的)捕获组匹配的内容,位于字符串 ( )\1的末尾。 实际上,只有当输入由相同的一半组成时,整个正则表达式才会匹配。$

  • $1作为-regex替换操作数,然后返回(第一个也是唯一的)捕获组匹配的内容,即输入字符串的前半部分。

请注意,这样的正则表达式效率低下,因为它需要大量回溯,因为事先不知道中点。
在这种情况下,使用非贪婪修饰符(+?而不是+)也可以,但实际上在性能方面似乎没有任何区别(推测使用.+?then 需要相同数量的“前向跟踪”尝试)。


推荐阅读