xlogI125’s blog

パソコン作業を効率化したい

PowerShell練習 CSVファイルをStrCmpLogicalWの順で並べ替える 2

メモ

  • csvファイルの読み込み
    • [List[PSCustomObject]](Import-Csv -Encoding UTF8 -LiteralPath $args[0])
  • 並べ替え
    • List.Sort(Comparer<PSObject>)
  • 並べ替えに使用する列名は決め打ち

使い捨てスクリプト

  • PowerShell.exeへのショートカット経由で実行
  • csvファイルの先頭行はデータの見出しとする
  • csvファイルの内容を列名"MySort"で並べ替え
  • 並べ替え前における順番(連番)を列名"MyOrderBefore"として追加
  • 並べ替え後における順番(連番)を列名"MyOrderAfter"として追加
  • 並べ替え後のcsvクリップボードにコピー
# PowerShell 5.1, Windows 11

# このスクリプトのファイル名
#  "%USERPROFILE%\Desktop\Sort_CSV_UTF8.ps1"
# エンコード
#  UTF-8 (BOM付き)

# ショートカット(.lnk)
#  リンク先(T):
#   PowerShell.exe -NoLogo -NoExit -NoProfile -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\Sort_CSV_UTF8.ps1"
#  作業フォルダー(S):
#   ""

using namespace System.Collections.Generic

Set-StrictMode -Version Latest

$VerbosePreference = "Continue"

$null | Set-Clipboard

if ($args.Length -eq 0) {
  Write-Verbose "`n`$args.Length -eq 0"
  return
}

Set-Location -LiteralPath (Split-Path -LiteralPath $args[0])

Write-Verbose @"
`n`$args`[0`]
$($args[0])`n`n
"@

# csvファイル(CSV UTF-8 (コンマ区切り))を読み込む
$a = [List[PSCustomObject]](Import-Csv -Encoding UTF8 -LiteralPath $args[0])

if ($null -eq $a) {
  Write-Verbose "`n`$null -eq `$a"
  return
}

if ($a.Count -eq 0) {
  Write-Verbose "`n`$a.Count -eq 0"
  return
}

Write-Verbose @"
`n`$a.Count
$($a.Count)`n`n
"@

Write-Verbose @"
`n並べ替え前
Get-Member -InputObject `$a`[0`] -MemberType Properties
$(Get-Member -InputObject $a[0] -MemberType Properties | Out-String)
"@

# 並べ替え前における順番(連番)を列名"MyOrderBefore"として追加
for ($i = 0; $i -lt $a.Count; $i++) {
  Add-Member -InputObject $a[$i] -NotePropertyName "MyOrderBefore" -NotePropertyValue ($i + 1)
}

Add-Type -Language CSharp -TypeDefinition @'
namespace Win32Functions {
  using System.Runtime.InteropServices;

  public class Win32StrCmpLogicalW {
    [DllImport(
      "Shlwapi.dll", CharSet = CharSet.Unicode, EntryPoint = "StrCmpLogicalW"
    )]
    public static extern int StrCmpLogicalW(
      [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
      [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );
  }
}

namespace MyNamespace {
  using System.Collections.Generic;
  using System.Management.Automation;

  public class MyClass : Comparer<PSObject> {
    private string propertyName;

    public MyClass(string propertyName) {
      this.propertyName = propertyName;
    }

    public override int Compare(PSObject x, PSObject y) {
      string str1 = x.Properties[propertyName].Value.ToString();
      string str2 = y.Properties[propertyName].Value.ToString();
      return Win32Functions.Win32StrCmpLogicalW.StrCmpLogicalW(str1, str2);
    }
  }
}
'@

# csvファイルの内容を列名"MySort"で並べ替え
try {
  $a.Sort([MyNamespace.MyClass]::new("MySort"))
}
catch {
  Write-Verbose "`n$_"
  return
}

# 並べ替え後における順番(連番)を列名"MyOrderAfter"として追加
for ($i = 0; $i -lt $a.Count; $i++) {
  Add-Member -InputObject $a[$i] -NotePropertyName "MyOrderAfter" -NotePropertyValue ($i + 1)
}

$b = $a | ConvertTo-Csv -NoTypeInformation

# 並べ替え後のcsvはクリップボードにコピー
$b | Set-Clipboard

Write-Output -InputObject $b

過去記事

dy100ms.hatenadiary.jp