查找模式之间的线条,并将第一行附加到线条

Find lines between a pattern, and append 1st line to lines

我有以下案例,我正在尝试在 Powershell 中编写脚本。我在 bash 终端上使用 Sed 完成了这个练习,但在 Powershell 中编写时遇到了问题。任何帮助将不胜感激。
sed -r -e '/^N/h;/^[N-]/d;G;s/(.*)\n(.*)/ /' <file>,文件格式没有 <> 个字符。每行第一个字母周围)

开始模式总是以 <N> 开始(每个块只有 1 个实例),开始之间的行以 <J>,结束模式总是 --

--------------
<N>ABC123
<J>SomethingHere1
<J>SomethingHere2
<J>SomethingHere3
--------------    <-- end of section

我试图在每个部分 <N> 中获取第一行,然后将其复制到同一部分中的每个 <J> 之后。例如:

<J>SomethingHere1    <N>ABC123
<J>SomethingHere2    <N>ABC123
<J>SomethingHere3    <N>ABC123

每个部分的 <J> 行数可以变化 (0-N)。在没有<J>的情况下,不需要做任何事情。

Powershell version:5.1.16299.611

以下基于管道的解决方案速度不快,但概念上直截​​了当 :

Get-Content file.txt | ForEach-Object {
  if ($_ -match '^-+$') { $newSect = $true }
  elseif ($newSect) { $firstSectionLine = $_; $newSect = $False }
  else { "{0}`t{1}" -f $_, $firstSectionLine }
}
  • 它一行一行地读取和处理行(手头的行反映在自动变量$_.

  • 它使用正则表达式 (^-+) 和 -match 运算符来识别部分分隔符;如果找到,标志 $newSect 被设置为表示 下一个 行是该部分的第一行数据。

  • 如果第一个数据行被命中,它被缓存在变量$firstSectionLine中,并且$newSect标志被重置。

  • 根据定义,所有其他行都是要附加第一条数据行的行,这是通过 -f 字符串格式化运算符使用制表符完成的。 (`t) 作为分隔符。


这是一个更快的 PSv4+ 解决方案,但是更复杂,它将整个输入文件读入预先记忆:

((Get-Content -Raw file.txt) -split '(?m)^-+(?:\r?\n)?' -ne '').ForEach({
  $firstLine, $otherLines = $_ -split '\r?\n' -ne ''
  foreach ($otherLine in $otherLines) { "{0}`t{1}" -f $otherLine, $firstLine }
})
  • Get-Content -Raw 以单个字符串的形式完整读入输入文件。

  • 它使用-split运算符将输入文件分割成多个部分,然后对每个部分进行处理。

  • 正则表达式 '(?m)^-+(?:\r?\n)?' 匹配节分隔线,可选择后跟换行符。

    • (?m)是多行选项,它使^$分别匹配每个的开始和结束:
    • \r?\n 以 CRLF (\r\n) 或 LF-only (\n) 形式匹配换行符。
    • (?:...)为非捕获组;使其成为非捕获可防止它匹配的内容包含在 -split.
    • 返回的元素中
    • -ne '' 过滤掉生成的空元素。
  • -split '\r?\n' 将每个部分分成单独的行。

如果性能仍然是一个问题,您可以使用 [IO.File]::ReadAllText("$PWD/file.txt").

来加快读取文件的速度