regex 从Powershell中以特定字符开头的行中删除Enter的正则表达式

m528fe3b  于 2023-02-25  发布在  Shell
关注(0)|答案(2)|浏览(106)

我有巨大的csv文件与数据,有些行是不正确的,并包含输入。当文件导入Excel,然后我需要手动纠正数百行。我有regex这是在记事本++工作,并从行中删除输入,这是不是在这种情况下以特定字符串开始“;“但是同一个正则表达式在PowerShell脚本中不起作用。
输入示例

;BP;7165378;XX_RAW;200SSS952;EU-PL;PL02;PL02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15:00:00;;;;Jhon Name;;;;;;;;9444253;;;;;;;;;;;;;"Jhon Name";;;;;;;;;;Jhon Name;;;;;;;;Final Check Approved;;;;;;;;;09.01.2023;;;;;Approve;;;;;;12077;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

它的外观应该是:

;BP;7165378;XX_RAW;200SSS952;EU-PL;PL02;PL02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15:00:00;;;;Jhon Name;;;;;;;;9444253;;;;;;;;;;;;;"Jhon Name";;;;;;;;;;Jhon Name;;;;;;;;Final Check Approved;;;;;;;;;09.01.2023;;;;;Approve;;;;;;12077;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

代码:

$content = Get-Content -path "C:\Users\TUF17\Desktop\File\Fix\xx_fix_temp.csv" 
$content -Replace '"\R(?!;)"', ' ' |  Out-File "C:\Users\TUF17\Desktop\File\Fix\xx_noenters.csv"
gudnpqoy

gudnpqoy1#

它与ps脚本中的行续行符\有关。
如果你想把文件的内容作为单个字符串而不是字符串数组来获取,我还建议添加-Raw,以便于替换。
我假设这是一个.csv文件您正在使用。

$content = Get-Content -Path "C:\Users\TUF17\Desktop\File\Fix\xx_fix_temp.csv" -Raw
$content -Replace '(?m)(^[^;].*)\r?\n(?!;)', '$1 ' |  Out-File "C:\Users\TUF17\Desktop\File\Fix\xx_noenters.csv"
a8jjtwal

a8jjtwal2#

根据对以下问题的有益评论:

  • 为了跨文本文件的*行执行替换 *,您需要**使用Get-Content-Raw**读取 * 整个 * 文件,或者执行 * 有状态 * 逐行处理,例如使用switch语句的-File参数。
  • 注:虽然您也可以通过将Get-Content(* 不带 * -Raw)与ForEach-Object调用组合来执行有状态的逐行处理,但这样的解决方案会慢得多-请参见this answer
  • 您的**regex'"\R(?!;)"'存在两个问题**:
  • 它意外地使用了嵌入式"引号。仅使用 * '...'引号。PowerShell * 没有 * 正则表达式文字的特殊语法-它只使用 * 字符串 *。

为了避免与PowerShell自己的预先字符串插值混淆,最好使用逐字的'...'字符串,而不是可扩展(插值)的"..."字符串-请参阅概念性的about_Quoting_Rules帮助主题。

      • \R是不受支持的正则表达式转义序列**;您的意思大概是**\r**,即CR字符。(运费,U+000D
  • 如果要匹配CRLF(Windows格式的换行符 * 序列 *),请使用\r\n
  • 如果要单独匹配LF(LINE FEED,U+000A)(Unix的换行符),请使用\n
  • 如果要匹配 * 两种 * 换行符格式,请使用\r?\n
  • 顺便说一句:虽然实际上很少单独使用CR *,但PowerShell也将独立的CR字符视为换行符,这就是为什么不带 * -RawGet-Content * 无法工作的原因,它读取 * 逐行 *(正如您所尝试的)。
    • Get-Content -Raw解决方案**(比switch -File更简单、更快,但需要整个文件两次放入内存):
# Adjust the '\r' part as needed (see above).
(Get-Content -Raw -LiteralPath $inFile) -replace '\r(?!;)' |
  Set-Content -NoNewLine -Encoding utf8 -LiteralPath $outFile

注:

  • 通过不为-replace指定替换操作数,命令 * 删除 * 所有后面没有;(?!;))的换行符,从而有效地将CR后面的行 * 直接 * 连接到前一行,这是基于示例输出的所需行为。
  • 对于保存 * text *,Set-ContentOut-File稍快一些(这里没有明显的区别,因为只写入了一个 * single * 大字符串)。
  • -NoNewLine防止(n个额外的)尾随换行符附加到文件中。
  • -Encoding utf8指定输出字符编码。请注意,PowerShell从不保留 * input * 字符编码,因此除非在 * output * 上使用-Encoding,否则将获得相应cmdlet的 * default * 字符编码,在 * Windows PowerShell * 中,该编码因cmdlet而异;在 * PowerShell(核心)7 +* 中,* 一致 * 默认值现在是无BOM的UTF-8。请注意,在 * Windows PowerShell * -Encoding utf8中,始终创建 * 带有 * BOM的文件;有关背景信息和解决方法,请参见this answer

相关问题