IT

*が\052として表示される理由:スクリプト書く時の注意点

本題

作成したスクリプトで値を取得したら、「*」が「\052」となっていて困った話です。

原因

*が\052のように表示される理由は、文字のエスケープシーケンスによるものです。

アスタリスク(*)は、ASCII文字コードで10進数の42番に割り当てられおり、これを8進数で表すと「052」になります。

そのため特段*として表示する処理を入れていないと、\052として出力されます。

API等では、*等の特殊文字をセキュリティの関係上エスケープして返却します。

遭遇したシーン

Route53の情報を一括でawsCLIで取得した時に発生

・期待した出力サンプル
"*.example.com"

・実際の出力サンプル
"\052.example.com"

実際のコード

#!/bin/bash
# エラー発生時に即座に終了
set -e

# 基本設定
DATE=$(date +%Y-%m-%d)
OUTPUT_DIR="route53_export_${DATE}"

# 出力ディレクトリを作成する関数
create_output_directory() {
    if [ -d "$OUTPUT_DIR" ]; then
        echo "警告: 既存ディレクトリが存在するため、タイムスタンプ付きで作成します"
        OUTPUT_DIR="${OUTPUT_DIR}_$(date +%H%M%S)"
    fi
    mkdir -p "$OUTPUT_DIR"
    echo "作成完了: $OUTPUT_DIR"
}

# Route53のホストゾーン情報をエクスポートする関数
export_hosted_zone() {
    local zone_id=${1#/hostedzone/}  # ゾーンIDからスラッシュを削除
    local zone_name=${2%.}           # 最後のドットを削除

    echo "ホストゾーンの出力: $zone_name ($zone_id)"

    # 安全なファイル名を生成
    local safe_zone_name=$(echo "$zone_name" | tr -d -c '[:alnum:]._-')
    local output_file="${safe_zone_name}_${zone_id}.json"
    local temp_file=$(mktemp)

    # ゾーン情報とレコードセットの取得
    aws route53 get-hosted-zone --id $zone_id | jq '.HostedZone' > "$temp_file"
    aws route53 list-resource-record-sets --hosted-zone-id $zone_id | \
        jq '.ResourceRecordSets' | \
        jq --slurpfile zone "$temp_file" '{
            "hostedZone": $zone[0],
            "records": .,
            "exportDate": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'"
        }' > "$OUTPUT_DIR/$output_file"

    rm "$temp_file"
    echo "- 出力先: $OUTPUT_DIR/$output_file"
    echo "- レコード数: $(jq '.records | length' "$OUTPUT_DIR/$output_file")"
}

# メイン処理
main() {
    echo "Route 53のエクスポートを開始します..."
    create_output_directory

    # ホストゾーン一覧の取得
    echo "ホストゾーン情報を取得中..."
    zones=$(aws route53 list-hosted-zones --output json)

    # ホストゾーンの処理
    zone_count=$(echo "$zones" | jq '.HostedZones | length')
    if [ "$zone_count" -eq 0 ]; then
        echo "ホストゾーンが見つかりません"
        exit 0
    fi

    echo "$zone_count 個のホストゾーンを検出"
    echo "--------------------------------"

    # 各ゾーンの処理
    echo "$zones" | jq -c '.HostedZones[] | {Id, Name}' | while read -r zone; do
        export_hosted_zone "$(echo "$zone" | jq -r '.Id')" "$(echo "$zone" | jq -r '.Name')"
    done

    echo "--------------------------------"
    echo "エクスポートが完了しました!"
    echo "出力ディレクトリ: $OUTPUT_DIR"
}

main

どういう処理を入れればいいか?

「ゾーン情報とレコードセットの取得」の処理で、出力前にjqで変換を入れてあげればOK

  • 修正後のコード
aws route53 list-resource-record-sets --hosted-zone-id $clean_zone_id | \
    jq '.ResourceRecordSets' | \
    jq --slurpfile zone "$temp_file" '{
        "hostedZone": $zone[0],
        "records": .,
        "exportDate": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'"
    }' | \
    jq 'walk(if type == "string" then gsub("\\\\052"; "*") else . end)' \
    > "$OUTPUT_DIR/$output_file"

最後に

文字コード系の処理は見落としやすいので、注意が必要ですね。
私はスクリプト作成して少し経ってから、人に言われて気づきました。。。

以降は注意していきたいと思います。

以上、どなたかのお役に立てば幸いです。

  • この記事を書いた人

緑川縁

ニートからシステムエンジニアになった人
クラウド案件をメインにやっています。
保持資格:CCNA,AWS SAA&SAP,秘書検定2級
趣味でボカロ曲作り始めました。

-IT
-