例如,我有第一个文本
today is sunny in the LA
and the temperature is 21C
today is cloudy in the NY
and the temperature is 18C
today is sunny in the DC
and the temperature is 25C
这是我想要的顺序:
18C
25C
21C
我想将第一个文件更改为与第二个文件相同的顺序,但不删除任何内容:
today is cloudy in the NY
and the temperature is 18C
today is sunny in the DC
and the temperature is 25C
today is sunny in the LA
and the temperature is 21C
答案 0 :(得分:2)
注意:下面的PSv3 +解决方案回答了一个不同问题:它根据段落中包含的温度值以数字方式对段落进行排序,而不是外部规定的命令。
这是一个简洁的解决方案,但请注意,它需要将输入文件整体读取到内存中(无论如何,Sort-Object
也会将其输入对象全部收集到内存中,因为它不使用临时文件来缓解潜在的记忆压力):
((Get-Content -Raw file.txt) -split '\r?\n\r?\n' -replace '\r?\n$' |
Sort-Object { [int] ($_ -replace '(?s).+ (\d+)C$', '$1') }) -join
[Environment]::NewLine * 2
(Get-Content -Raw file.txt)
将输入文件作为单个多行字符串整体读取到内存中。
-split '\r?\n\r?\n'
将多行字符串分成几段段落(由空行分隔的几行行),并且-replace '\r?\n$'
从段落中删除尾随的换行符(如果有的话)在文件的最后。
\r?\n
与Windows样式的CRLF和Unix样式的仅LF换行符匹配。 Sort-Object { [int] ($_ -replace '(?s).+ (\d+)C$', '$1') })
对段落进行数字排序,以每个段落末尾的温度编号(例如18
)为例。
$_
代表当前输入的段落。-replace '...', '...'
基于正则表达式执行字符串替换,在这种情况下,该表达式将从段落末尾提取温度数字字符串。
Get-Help about_Regular_Expressions
;有关-replace
运算符的信息,请参见Get-Help about_Comparison_Operators
。[int]
将数字字符串转换为整数,以进行正确的数字排序。 -join [Environment]::NewLine * 2
将排序后的段落重新组合为一个多行字符串,各段落之间用空行分隔。
[Environment]::NewLine
是适合平台的换行符序列;您也可以将换行符硬编码为"`r`n"
(CRLF)或"`n"
(LF)。您可以通过添加诸如
之类的内容将输出发送到新文件
... | Set-Content sortedFile.txt
(默认情况下,文件在Windows PowerShell中使用“ ANSI”编码,而在PowerShell Core 中使用UTF-8编码;根据需要使用-Encoding
)。>
由于将整个输入文件预先读取到内存中,因此 可以将结果直接写回输入文件(... | Set-Content file.txt
),但这会带来轻微的风险数据丢失,即在完成之前中断写入。
答案 1 :(得分:1)
Nas' helpful answer有效,但是它是O(m * n)运算;即,以规定的顺序输出m段,输入n段,则需要m * n次运算。如果要输出所有 输入段落(按规定的顺序),即,如果m等于n,则工作量为二次。
以下PSv4 +解决方案将更好地扩展,因为它只需要 linear 而不是 quadratic :
# The tokens prescribing the sort order, which may come from
# another file read with Get-Content, for instance.
$tokensToSortBy = '18C', '25C', '21C'
# Create a hashtable that indexes the input file's paragraphs by the sort
# token embedded in each.
((Get-Content -Raw file.txt) -split '\r?\n\r?\n' -replace '\r?\n$').ForEach({
$htParagraphsBySortToken[$_ -replace '(?s).* (\d+C)$(?:\r?\n)?', '$1'] = $_
})
# Loop over the tokens prescribing the sort order, and retrieve the
# corresponding paragraph, then reassemble the paragraphs into a single,
# multi-line string with -join
$tokensToSortBy.ForEach({ $htParagraphsBySortToken[$_] }) -join [Environment]::NewLine * 2
(Get-Content -Raw file.txt)
将输入文件作为单个多行字符串整体读取到内存中。
-split '\r?\n\r?\n'
将多行字符串分成几段段落(由空行分隔的几行行),并且-replace '\r?\n$'
从段落中删除尾随的换行符(如果有的话)在文件的最后。
\r?\n
与Windows样式的CRLF和Unix样式的仅LF换行符匹配。 $_ -replace '(?s).* (\d+C)$(?:\r?\n)?', '$1'
从每个段落中提取排序令牌(例如25C
),这成为哈希表的键。
$_
代表当前输入的段落。-replace '...', '...'
基于正则表达式执行字符串替换。
Get-Help about_Regular_Expressions
;有关-replace
运算符的信息,请参见Get-Help about_Comparison_Operators
。 -join [Environment]::NewLine * 2
将排序后的段落重新组合为一个多行字符串,各段落之间用空行分隔。
[Environment]::NewLine
是适合平台的换行符序列;您也可以将换行符硬编码为"`r`n"
(CRLF)或"`n"
(LF)。您可以通过添加诸如
之类的内容将输出发送到新文件
... | Set-Content sortedFile.txt
至最后一条语句(默认情况下,文件在Windows PowerShell中使用“ ANSI”编码,而在PowerShell Core 中使用UTF-8编码;根据需要使用-Encoding
)。
答案 2 :(得分:0)
$text = Get-Content -path C:\text.txt
$order = '18C','25C','21C'
foreach ($item in $order)
{
$text | ForEach-Object {
if ($_ -match "$item`$") { # `$ to match string at the end of the line
Write-Output $text[($_.ReadCount-2)..($_.ReadCount)] # output lines before and after match
}
}
}