首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Powershell `-replace`正则表达式与换行符不匹配

Powershell `-replace`正则表达式与换行符不匹配
EN

Stack Overflow用户
提问于 2021-10-28 21:39:48
回答 3查看 153关注 0票数 1

我正在尝试使用正则表达式清理一些html文件(是的,我见过the post。我并不是一般地解析html),我想删除所有不包含标签的行。我的脚本如下:

代码语言:javascript
运行
复制
Remove-Item $args[1]
$text = (Get-Content -Path $args[0] -Raw)
$text = $text -replace "^\s*\r?\n"
New-Item -Path $args[1] -ItemType File -Force -Value $text

有一堆其他的东西我想要替换,但我主要是尝试修复

我可以验证内部正则表达式是否正常工作: VSCode (它使用JS正则表达式,而不是powershell的.NET正则表达式)使用提供的正则表达式正确地匹配(并替换)有问题的行。

我知道这个Powershell is Special,所以我将Get-Content的输出转换为一个嵌入了换行符的原始字符串。这并没有什么帮助。

我可以验证其他函数(即remove-itemnew-item)是否正常工作,以及其他正则表达式是否正常工作,方法是将正则文本从"^\s*\r?\n"更改为"p", "abc",并查看p标记是否都变成了abc标记。

此外,正则表达式\s*\r?\n可以工作,因此并不是正则表达式找不到换行符。

正则表达式\A\s*\r?\n也不起作用,这意味着它与PowerShell如何找到字符串的开始/结束位置有关。

到底怎么回事?

代码语言:javascript
运行
复制
<p>This is some text</p>

(the next line has a bunch of spaces)
               

<p>this is some more text</p>

仅作为参考,当使用VSCode的JS regex引擎时,我的regex应该(并且确实)与上面示例的第二、第四和第五行匹配(我相信类似于PCRE)

最后,对正则表达式进行反编译:

代码语言:javascript
运行
复制
^         from the start of the string
 \s*      match any number of whitespaces
    \r?   possibly followed by a carriage return
       \n then a newline
EN

回答 3

Stack Overflow用户

发布于 2021-10-28 21:48:11

当你这样做的时候

代码语言:javascript
运行
复制
$text = (Get-Content -Path $args[0] -Raw)

$text中有行结尾,您的正则表达式可以匹配它们。

^锚点也可以匹配任何行的开头,但是,有一个特殊的标志要使用:

代码语言:javascript
运行
复制
$text = $text -replace '(?m)^\s*\n'

\s模式涵盖了回车,不需要担心它们,并使用\r?

说明

代码语言:javascript
运行
复制
--------------------------------------------------------------------------------
  (?m)                     set flags for this block (with ^ and $
                           matching start and end of line) 
--------------------------------------------------------------------------------
  ^                        the beginning of a "line"
--------------------------------------------------------------------------------
  \s*                      whitespace (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  \n                       '\n' (newline)
票数 4
EN

Stack Overflow用户

发布于 2021-10-28 22:22:49

Ryszard Czech's helpful answer很好地解释了您的方法的问题,并提供了有效的解决方案。

从本质上讲,代码是希望从文件<>e210>中消除空或空白(全空白)行。

一种更简单但速度较慢的解决方案是利用Get-Content的默认逐行流,并结合许多PowerShell运算符对输入数组进行操作的能力,在这种情况下,它们充当过滤器。

在这种情况下,您可以利用-match operator (根据需要调整-Encoding ):

代码语言:javascript
运行
复制
@(Get-Content -Path $args[0]) -match '\S' | Set-Content -Encoding UTF8 $args[1]

以上代码将文件$args[0]中至少包含一个非空格字符(\S)的所有行传递给Set-Content,后者将过滤后的行保存到目标文件$args[1]

票数 4
EN

Stack Overflow用户

发布于 2021-10-28 21:39:48

诀窍是,您实际上不会有超过一行可以匹配。

当您使用-Raw将文件转换为字符串时,您将其设置为一行。因此,^将只匹配文件的开头,因为这是正则表达式引擎可以找到的唯一字符串开头标识符。

解决此问题的方法是匹配前一行末尾的换行符或匹配文件的开头,然后将其带入替换位置,如下所示:

代码语言:javascript
运行
复制
$text = $text -replace "(^|\n)\s*\r?\n","$1"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69761254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档