PowerShell にも diff
がある?
あるにはありますが、初心者なかせです。わたしははまりました。
たとえばつぎのふたつのテキスト ファイルで PS でも diff
ってみますと、個人的には残念な結果をえます。
PS> cat .\poem.txt
Great fleas have little fleas
upon their backs to bite 'em,
And little fleas have lesser fleas,
and so ad infinitum.
And the great fleas themselves, in turn,
have greater fleas to go on;
While these again have greater still,
and greater still, and so on.
PS> cat .\new_poem.txt
Great fleas have little fleas
upon their backs to bite them,
And little fleas have lesser fleas,
and so on ad infinitum.
And the great fleas themselves, in turn,
have greater fleas to go on;
While these again have greater still,
and greater still, and so on.
PS> diff .\poem.txt .\new_poem.txt
InputObject SideIndicator
----------- -------------
.\new_poem.txt =>
.\poem.txt <=
UNIX 系ならつぎのような出力がえられるところ。
$ diff poem.txt new_poem.txt
2c2
< upon their backs to bite 'em,
---
> upon their backs to bite them,
4c4
< and so ad infinitum.
---
> and so on ad infinitum.
PS の diff
は Compare-Object
の alias
-
Get-Alias -Name diff
とするとdiff -> Compare-Object
とでます。 - 逆に
Get-Alias -Definition Compare-Object
とするとデフォルトでcompare
とdiff
とがでます。
Compare-Object
の構文は
PS> Get-Command -Name Compare-Object -Syntax
Compare-Object [-ReferenceObject] <psobject[]> [-DifferenceObject] <psobject[]> [-SyncWindow <int>] [-Property <Object[]>] [-ExcludeDifferent] [-IncludeEqual] [-PassThru] [-Culture <string>] [-CaseSensitive] [<CommonParameters>]
すなわち .\poem.txt
と .\new_poem.txt
をそれぞれ単に psobject (を継承する string) の要素数 1 の配列としてうけとった模様です。
というわけで、ファイルの内容を Get しないとなりません。いろいろ略さずにかくと1
PS> Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt)
InputObject SideIndicator
----------- -------------
upon their backs to bite them, =>
and so on ad infinitum. =>
upon their backs to bite 'em, <=
and so ad infinitum. <=
行番号をうるには
しかし、まだ不満です。
- 行番号が表示されない。
- 対応する行が隣接していない。
Get-Content -Path .\poem.txt | Get-Member
してみると ReadCount
という NoteProperty がありますが、これは Compare-Object
の結果の InputObject
に温存されています。このことを利用してようやくのぞましい結果をえられたのでした。
PS> Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt) | Select-Object -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, * | Sort-Object -Property ReadCount
ReadCount InputObject SideIndicator
--------- ----------- -------------
2 upon their backs to bite 'em, <=
2 upon their backs to bite them, =>
4 and so ad infinitum. <=
4 and so on ad infinitum. =>
2020/04/17 追記
上記 Select-Object
ではあたらしいオブジェクトを生成しています2。
Sorting Objects | Using hash tables をよみかえしていてきづいたのですが、ハッシュ テーブルをつかえばふかいところにあるプロパティでもソートできますと。あとは表示のときに ReadCount
をおもてにもってくるのでよければ Format-Table
にまかせて
Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt) |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
Format-Table -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, *
ただ、ながい。常用するようなら function
でくるむところでしょうか。