PowerShellのハッシュテーブルで大文字小文字の重複による「Duplicate keys」エラーを回避した話

PowerShellの「hashtable duplicate keys」エラーのせいで、テキストの一括置換作業がストップして困っている方向けの記事です。大文字小文字を区別しないPowerShellのハッシュテーブルの制限を回避し、作業を即座に完了させる方法を紹介します(実際の運用ログに基づく記録です)。

問題の状況

今回行おうとした作業は、PowerShellを使ってドキュメント内にある特定のカラーコード(hex color string)を一括置換(replace)することでした。大文字小文字が混在するカラーコードの値をマッピングするため、以下のようにハッシュテーブルを定義しました。

$replacements = @{'#1e2a45'='#f6f7f8'; '#1E2A45'='#f6f7f8'}

しかし、このコードを実行した直後、ハッシュテーブルの定義段階でエラーが発生し、スクリプトが停止してしまいました。

PowerShell hashtable duplicate keys エラーの挙動

実行時にコンソールに出力されたエラーメッセージは以下の通りです。

Duplicate keys '#1E2A45' are not allowed in hash literals

原因はPowerShellの仕様にあります。PowerShellはデフォルトで、ハッシュテーブルのキーを大文字小文字を区別せずに(case-insensitive)比較します。そのため、#1e2a45#1E2A45 を別々のキーではなく「同一キーの重複定義」と判定してしまい、例外を発生させたのです。

環境

  • OS: Windows
  • ツールバージョン: Windows PowerShell 5.1
  • 自動化スタック: hashtable literal (@{})

試したものの失敗したアプローチ

最初に試した回避策は、リテラル表記(@{})の代わりに、.NETオブジェクトを直接生成する New-Object System.Collections.Hashtable を使う方法でした。しかし、これも内部的には同様に大文字小文字を区別しない比較メカニズムが働くため、同じエラーが発生して失敗に終わりました。

「大文字小文字くらい区別してくれ」と祈るような気持ちでしたが、PowerShellは頑なにエラーを吐き出すばかり。やはり、融通の利かないツールを無理に説得しようとするのは時間の無駄ですね。

最終的な解決策

結局、PowerShellに固執するのをやめ、テキスト処理がより柔軟に行えるPythonに切り替えて迂回することで解決しました。Pythonの re モジュールを使い、大文字小文字を区別せずにマッチングする re.compile(re.escape(old), re.I) を適用。これにより、大文字小文字が異なる同一のカラーコード値を一度に安全に置換することができました。

使用したコード

# 置換対象のリスト(実際の運用記録に基づく)
swaps = [
 ('#1e2a45', '#f6f7f8'),
 ('#1E2A45', '#f6f7f8')
]

# 大文字小文字を区別せずに置換を実行
for old, new in swaps:
 pat = re.compile(re.escape(old), re.I)
 content = pat.sub(new, content)

検証結果

作成したPythonスクリプトを実行したところ、計131箇所の置換対象を、大文字小文字を区別せずわずか1回の実行で完璧に置換できました。重複キーのエラーに悩まされることもなく、きれいに処理が完了したことを確認しました。

現在のステータス

fixed(解決済み)

同じ問題に直面している方へ

PowerShellの「hashtable duplicate keys」エラーで消耗しているなら、PowerShell内部で複雑な .NET Dictionaryを宣言しようと無理をする必要はありません。テキスト置換のようなタスクであれば、Pythonの re.I オプションを使う方が、精神衛生上も生産性の面でも遥かに早くて確実な道です。

Category Coverage Notice

This article follows our label-specific editorial criteria. Details:

ToolSignal Pro Editorial

ToolSignal Pro는 AI·IT·소프트웨어 트렌드를 다루는 종합 IT 인사이트 매거진입니다.

이전 글 다음 글