Ten*_*ore 6 powershell regex string-manipulation
我意识到我在问一个已经被问过和回答过的类似问题,但我无法推断出我需要的答案,因为正则表达式和正则表达式引擎足够不同。我有硬件资产管理日志,它们以管道分隔,但不是端点之间的主要分隔。日志如下所示:
|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
Run Code Online (Sandbox Code Playgroud)
我想要做的是用|
回车替换每 6 次,看起来像这样:
|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1
|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2
|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
Run Code Online (Sandbox Code Playgroud)
我得到的最接近的选择每个端点,但我不太确定如何使用 powershell 来利用它。
[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*
Run Code Online (Sandbox Code Playgroud)
我熟悉 PS 中的替换命令,我想象最终结果会是这样的:
$hosts = $hosts -replace "<highspeed_low_drag_velcro_snap_regex_here>","\r\n"
Run Code Online (Sandbox Code Playgroud)
提前致谢!
好的,所以这个实际上有点棘手。可以说,正则表达式不是这项工作的最佳工具,但它可以做到。
-replace "(?<=^((\|[^|]*){5})+)\|","`n|"
Run Code Online (Sandbox Code Playgroud)
我会试着引导你完成它:
(?<=)
部分是回顾。这意味着一切的=
和)
是匹配的,但不是取代。So^((\|[^|]*){5})+
用作条件- 仅当此位与预期替换之前的文本匹配时才会发生替换。^((\|[^|]*){5})*[^|]*
部分可以概括为“从行首 ( ^
),匹配 5 个|
s 的集合,然后将文本匹配到下一个|
”。
^
很重要 - 否则它可以匹配行中的任何地方,并且无法保证|
之前有多少个s。|
在正则表达式中有特殊含义,需要转义:\|
. 在字符类 ( []
) 中时不需要对其进行转义。[^|]*
意思是“直到下一个文本|
”——更专业地说,“尽可能多的字符|
”——更技术地说“尽可能多地重复[^|]
字符类,其中该字符类匹配除|
“以外的任何字符。*
表示“前一个字符的零次或多次重复,尽可能多”(\|[^|]*)
意味着 match|
后跟尽可能多的字符,直到下一个|
. 这将匹配|text
{5}
表示将前面的标记准确重复 5 次。它完全等同于将前面的标记复制粘贴 5 次。所以这将匹配|text|text|text|text|text
((\|[^|]*){5})+
是整个组的一次或多次重复。所以它可以匹配|text|text|text|text|text
、|text|text|text|text|text|text|text|text|text|text
等 - 以 5 的倍数。我们使用+
代替 的原因*
是我们不想匹配空组并替换第一个|
。|
的5 |
s的倍数替换a ,从行的开头开始。\|
作为要替换的实际文本,前面是匹配的lookbehind。以您的示例为例|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
,它将匹配以下内容:
|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1**|**STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2**|**STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
Run Code Online (Sandbox Code Playgroud)您会在此处注意到(如果您还没有),您实际上是在尝试每5th |
减去第一个而不是每6th替换一次。但是lookbehind方法相当干净地处理“减去第一个”的情况。
现在是替换字符串。
\n
,我们实际上想要,`n
因为 PowerShell 转义字符是`
. 请注意,这仅在替换字符串中是必需的;在正则表达式本身中,您仍将使用\n
该文字序列传递给正则表达式引擎。|
在每一行都有一个前导,我们需要|
在新行之后添加一个新的。这是可行的,因为您的原始行不以 a 结尾|
,因此在行尾没有任何可替换的内容,因此我们不会以额外的新行结束,也不会以 结尾|
。如果您更喜欢更传统的捕获组方法:
-replace "((?:[^|]+\|){4}[^|]+)\|","`$1`n|"
Run Code Online (Sandbox Code Playgroud)
弄清楚这是如何工作的留给读者作为练习;) 提示:$1
反向引用必须被转义(使用`
),否则 PowerShell 会将其解释为 shell 变量。
归档时间: |
|
查看次数: |
1488 次 |
最近记录: |