查找模式之间的线条,并将第一行附加到线条
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")
.
来加快读取文件的速度
我有以下案例,我正在尝试在 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")
.