如何在Powershell中按特定顺序对txt文件排序

如何在Powershell中按特定顺序对txt文件排序,powershell,Powershell,例如,我有第一个文本 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

例如,我有第一个文本

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

注意:下面的PSv3+解决方案回答了一个不同的问题:它根据段落中包含的温度值对段落进行数字排序,而不是按照外部规定的顺序

  • 因此,考虑到问题的一般标题,它可能仍然很有意义
  • 有关所问问题的答案,请参阅

这里有一个简洁的解决方案,但请注意,它需要将输入文件作为一个整体读取到内存中(在任何情况下,
Sort Object
也会在内存中收集其所有输入对象,因为它不使用临时文件来缓解潜在的内存压力):

  • (Get Content-Raw file.txt)
    将输入文件作为单个多行字符串整体读取到内存中

  • -split'\r?\n\r?\n'
    将多行字符串拆分为一个段落数组(由空行分隔的行块),并且
    -replace'\r?\n$'
    从文件末尾的段落中删除尾随的换行符(如果有)

    • Regex
      \r?\n
      同时匹配Windows样式的CRLF和Unix样式的LF纯换行符
  • 排序对象{[int]($)-replace'(?s)。+(\d+)C$,'$1')}
    根据每个段落末尾的温度编号对段落进行数字排序(例如
    18

    • $表示手边的输入段落
    • -替换“…”,“…”
      基于正则表达式执行字符串替换,在本例中,正则表达式从段落末尾提取温度编号字符串。
      • 有关正则表达式和
        -replace
        运算符的信息,请参阅
    • Cast
      [int]
      将数字字符串转换为整数以进行正确的数字排序
  • -join[Environment]:NewLine*2
    将已排序的段落重新组合为一个多行字符串,段落之间用空行分隔

    • [环境]:换行符
      是适合平台的换行符序列;您也可以将换行代码硬编码为
      “`r`n”
      (CRLF)或
      “`n”
      (LF)
您可以通过添加类似
…|设置Content sortedFile.txt
(默认情况下,文件“ANSI”-在Windows PowerShell中编码,UTF-8-在PowerShell核心中编码;根据需要使用
-编码


由于整个输入文件预先读入内存,因此可以将结果直接写回输入文件(
…| Set Content file.txt
),但这样做有轻微的数据丢失风险,也就是说,如果书写在完成之前中断。

注意:下面的PSv3+解决方案回答了一个不同的问题:它根据段落中包含的温度值对段落进行数字排序,而不是按照外部规定的顺序

  • 因此,考虑到问题的一般标题,它可能仍然很有意义
  • 有关所问问题的答案,请参阅

这里有一个简洁的解决方案,但请注意,它需要将输入文件作为一个整体读取到内存中(在任何情况下,
Sort Object
也会在内存中收集其所有输入对象,因为它不使用临时文件来缓解潜在的内存压力):

  • (Get Content-Raw file.txt)
    将输入文件作为单个多行字符串整体读取到内存中

  • -split'\r?\n\r?\n'
    将多行字符串拆分为一个段落数组(由空行分隔的行块),并且
    -replace'\r?\n$'
    从文件末尾的段落中删除尾随的换行符(如果有)

    • Regex
      \r?\n
      同时匹配Windows样式的CRLF和Unix样式的LF纯换行符
  • 排序对象{[int]($)-replace'(?s)。+(\d+)C$,'$1')}
    根据每个段落末尾的温度编号对段落进行数字排序(例如
    18

    • $表示手边的输入段落
    • -替换“…”,“…”
      基于正则表达式执行字符串替换,在本例中,正则表达式从段落末尾提取温度编号字符串。
      • 有关正则表达式和
        -replace
        运算符的信息,请参阅
    • Cast
      [int]
      将数字字符串转换为整数以进行正确的数字排序
  • -join[Environment]:NewLine*2
    将已排序的段落重新组合为一个多行字符串,段落之间用空行分隔

    • [环境]:换行符
      是适合平台的换行符序列;您也可以将换行代码硬编码为
      “`r`n”
      (CRLF)或
      “`n”
      (LF)
您可以通过添加类似
…|设置Content sortedFile.txt
(默认情况下,文件“ANSI”-在Windows PowerShell中编码,UTF-8-在PowerShell核心中编码;根据需要使用
-编码

由于整个输入文件是预先读入内存的,因此可以将结果直接写回输入文件(
…| Set Content file.txt
),但这样做有轻微的数据丢失风险,即如果在完成之前中断写入。

工作,但这是一个O(m*n)操作;也就是说,在m个段落按规定顺序输出和n个输入段落的情况下,需要m*n个操作;如果要输出所有输入段落(在
$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
        }
    }
}
((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
# 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