#!/usr/bin/env sh # normalize-name — 正規化一個名稱字串,讓同一個名稱的不同打法算出同一個結果。 # 用法: # normalize-name.sh # 規則(依序套用): # 1. Unicode NFC 正規化 # 2. 去除頭尾空白 # 3. 內部連續空白(含全形空白)壓成一個半形空白 # 4. 英數全形字元轉半形(只轉英數,其他全形字元如標點不動) # 大小寫不在正規化範圍內,維持原樣、視為不同名稱。 # 例子: # normalize-name.sh "我的 計畫" -> 我的 計畫 # normalize-name.sh " Abc1 " -> Abc1 # 結束碼: 0=成功 1=這台機器沒有 python3,算不出正規化結果 2=用法錯誤:沒有給文字 set -eu if [ "$#" -lt 1 ]; then echo 'usage: normalize-name.sh ' >&2 exit 2 fi if ! command -v python3 >/dev/null 2>&1; then echo 'no python3 found' >&2 exit 1 fi printf '%s' "$1" | python3 -c ' import sys, re, unicodedata FULLWIDTH_OFFSET = 0xFEE0 # Unicode 全形英數區塊相對半形區塊的固定位移量 def to_halfwidth_alnum(ch): if ("0" <= ch <= "9") or ("A" <= ch <= "Z") or ("a" <= ch <= "z"): return chr(ord(ch) - FULLWIDTH_OFFSET) return ch name = unicodedata.normalize("NFC", sys.stdin.read()) name = name.strip() name = re.sub(r"[ \t ]+", " ", name).strip() # 只轉英數的全形字元,其他全形字元(例如全形標點)不動——只轉英數是規則本身 # 的範圍,不是整段跑 NFKC;NFKC 連標點都會改寫,會讓名稱的視覺呈現跟著變。 name = "".join(to_halfwidth_alnum(c) for c in name) sys.stdout.write(name) '