此问题已在此处有答案:
Regex how to replace <'string'> with a new line but keep the 'string'(3个答案)
上个月关门了。
我有一些文本通过$String = Get-Content -Path 'c:\temp\mytext.txt' -Raw
导入为单个字符串:
Lorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
- red
- green
- blue
Lorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
ac adipiscing mauris ante class placerat per sem quisque phasellus sociosqu, mollis
- red
- green
- blue
bluorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
`
我想在以-
开头的第一行之前("- red"
的行)和以-
开头的最后一行之后("- blue"
的行)添加一个新行,输出应该如下所示:
Lorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
- red
- green
- blue
Lorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
ac adipiscing mauris ante class placerat per sem quisque phasellus sociosqu, mollis
- red
- green
- blue
bluorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
对于以-
开头的第一行,根据regex101.com,这个RegEx看起来是它,\n-\s.*(\n)[^-]
,但是当我尝试将其应用于PowerShell,$String -replace '\n-\s.*(\n)[^-]', '\n$1'
时,该行本身被截断,即使捕获组$1
由单个令牌\n
组成。
同样,对于以-
开头的最后一行,根据regex101.com,这个RegEx看起来是\n-\s.*(\n)[^-]
,但在PowerShell中,$String -replace '\n-\s.*(\n)[^-]', '$1\n'
给了我:
Lorem ipsum et cras praesent mollis ullamcorper laoreet mauris imperdiet quisque
ac adipiscing mauris ante class placerat per sem quisque phasellus sociosqu, mollis
- red
\ngreen
...
我的RegEx很弱,我尽力使regex101.com的设置符合PowerShell的设置,但这里有些东西不对劲。
任何帮助将不胜感激!
2条答案
按热度按时间ar5n3qh51#
tl;dr:
替换:
'$1\n'
使用:
"
$1n"
,或者-为了概念清晰-使用('$1{0}' -f "
n")`背景信息:
\
没有特殊的含义,因此在-replace
运算符的替换操作数中包含\n
会导致\n
被包含。"..."
)和escape sequence ``n`,使用PowerShell的[escape character](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Special_Characters)
,即所谓的 backtick。$1
是一个要传递给.NET的正则表达式引擎的占位符,并且考虑到$1
看起来也像一个 *PowerShell变量引用 ,在"..."
中,你必须 * 转义$
char. 以防止 * 扩展 *(PowerShell基于变量的预先字符串插值),因此上面使用了``$`。-replace
在后台使用System.Text.RegularExpressions.Regex.Replace()
,它的替换(替换)操作数Map到replacement
参数,这不是一个正则表达式,它本身不理解基于\
的转义序列-它只知道$
前缀标记,引用regex匹配的元素(例如$1
引用第一个捕获组捕获的内容)。"..."
字符串(而不是逐字的@"..."
字符串),类似"$1\n"
的东西会导致 C# 将\n
转义序列 * 预先 * 展开(变成一个字面LF字符)。它会留下$
单独,因为这个字符。在C#字符串中没有特殊含义),这是regex101.com在使用.NET (C#)
风格时假定的行为。('$1{0}' -f "
n")使用
-f(PowerShell的格式操作符),是
"$1
n"的概念上更清晰的替代方案,因为它使用 * 逐字 * PowerShell字符串文字
'...',并带有占位符(
{0}),它被替换为 *expandable* 字符串文字的值(
"..."`),明确哪些部分是由前置字符串插值提供的,哪些部分由.NET正则表达式引擎解释。uplii1fm2#
我发现同时处理这两种情况更容易。mklement0的答案提供了非常清晰的螺母和螺栓。基本上,这个解决方案从一个破折号开始匹配,直到一个新的行后面没有一个破折号。