数据转换脚本#

脚本说明#

数据转换脚本用于在不同数据格式之间转换数据,包括JSON、XML、CSV、YAML等格式的相互转换。

脚本代码#

#!/bin/bash

# 数据转换脚本
# 功能:在不同数据格式之间转换数据
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
INPUT_FILE=""
OUTPUT_FILE=""
INPUT_FORMAT=""
OUTPUT_FORMAT=""
PRETTY_PRINT=false

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

# 检查输入文件
check_input_file() {
    if [ ! -f "$INPUT_FILE" ]; then
        log_error "输入文件不存在: $INPUT_FILE"
        return 1
    fi
    
    if [ ! -r "$INPUT_FILE" ]; then
        log_error "输入文件不可读: $INPUT_FILE"
        return 1
    fi
    
    return 0
}

# JSON转XML
json_to_xml() {
    local input=$1
    local output=$2
    
    log_info "JSON转XML: $input -> $output"
    
    # 使用python进行转换
    python3 <<EOF
import json
import xml.etree.ElementTree as ET
from xml.dom import minidom

# 读取JSON
with open('$input', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 转换为XML
def json_to_xml(data, root_tag='root'):
    if isinstance(data, dict):
        elem = ET.Element(root_tag)
        for key, value in data.items():
            elem.append(json_to_xml(value, key))
        return elem
    elif isinstance(data, list):
        elem = ET.Element(root_tag)
        for item in data:
            elem.append(json_to_xml(item, 'item'))
        return elem
    else:
        elem = ET.Element(root_tag)
        elem.text = str(data)
        return elem

xml_root = json_to_xml(data)
xml_str = ET.tostring(xml_root, encoding='unicode')

# 美化XML
dom = minidom.parseString(xml_str)
pretty_xml = dom.toprettyxml(indent='  ')

# 写入文件
with open('$output', 'w', encoding='utf-8') as f:
    f.write(pretty_xml)

print("转换完成")
EOF
}

# XML转JSON
xml_to_json() {
    local input=$1
    local output=$2
    
    log_info "XML转JSON: $input -> $output"
    
    # 使用python进行转换
    python3 <<EOF
import xml.etree.ElementTree as ET
import json

# 读取XML
tree = ET.parse('$input')
root = tree.getroot()

# 转换为JSON
def xml_to_json(element):
    result = {}
    for child in element:
        if len(child) == 0:
            result[child.tag] = child.text
        else:
            result[child.tag] = xml_to_json(child)
    return result

json_data = xml_to_json(root)

# 写入JSON文件
with open('$output', 'w', encoding='utf-8') as f:
    if $PRETTY_PRINT:
        json.dump(json_data, f, indent=2, ensure_ascii=False)
    else:
        json.dump(json_data, f, ensure_ascii=False)

print("转换完成")
EOF
}

# JSON转CSV
json_to_csv() {
    local input=$1
    local output=$2
    
    log_info "JSON转CSV: $input -> $output"
    
    # 使用python进行转换
    python3 <<EOF
import json
import csv

# 读取JSON
with open('$input', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 确保数据是列表
if not isinstance(data, list):
    data = [data]

# 提取所有字段
fields = set()
for item in data:
    if isinstance(item, dict):
        fields.update(item.keys())
fields = sorted(fields)

# 写入CSV
with open('$output', 'w', encoding='utf-8', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=fields)
    writer.writeheader()
    writer.writerows(data)

print("转换完成")
EOF
}

# CSV转JSON
csv_to_json() {
    local input=$1
    local output=$2
    
    log_info "CSV转JSON: $input -> $output"
    
    # 使用python进行转换
    python3 <<EOF
import json
import csv

# 读取CSV
data = []
with open('$input', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        data.append(row)

# 写入JSON
with open('$output', 'w', encoding='utf-8') as f:
    if $PRETTY_PRINT:
        json.dump(data, f, indent=2, ensure_ascii=False)
    else:
        json.dump(data, f, ensure_ascii=False)

print("转换完成")
EOF
}

# JSON转YAML
json_to_yaml() {
    local input=$1
    local output=$2
    
    log_info "JSON转YAML: $input -> $output"
    
    # 检查pyyaml是否安装
    if ! python3 -c "import yaml" 2>/dev/null; then
        log_error "需要安装pyyaml: pip install pyyaml"
        return 1
    fi
    
    # 使用python进行转换
    python3 <<EOF
import json
import yaml

# 读取JSON
with open('$input', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 写入YAML
with open('$output', 'w', encoding='utf-8') as f:
    yaml.dump(data, f, allow_unicode=True, default_flow_style=False)

print("转换完成")
EOF
}

# YAML转JSON
yaml_to_json() {
    local input=$1
    local output=$2
    
    log_info "YAML转JSON: $input -> $output"
    
    # 检查pyyaml是否安装
    if ! python3 -c "import yaml" 2>/dev/null; then
        log_error "需要安装pyyaml: pip install pyyaml"
        return 1
    fi
    
    # 使用python进行转换
    python3 <<EOF
import json
import yaml

# 读取YAML
with open('$input', 'r', encoding='utf-8') as f:
    data = yaml.safe_load(f)

# 写入JSON
with open('$output', 'w', encoding='utf-8') as f:
    if $PRETTY_PRINT:
        json.dump(data, f, indent=2, ensure_ascii=False)
    else:
        json.dump(data, f, ensure_ascii=False)

print("转换完成")
EOF
}

# XML转CSV
xml_to_csv() {
    local input=$1
    local output=$2
    
    log_info "XML转CSV: $input -> $output"
    
    # 先转换为JSON,再转换为CSV
    local temp_json=$(mktemp)
    
    if xml_to_json "$input" "$temp_json"; then
        json_to_csv "$temp_json" "$output"
        rm -f "$temp_json"
    else
        rm -f "$temp_json"
        return 1
    fi
}

# CSV转XML
csv_to_xml() {
    local input=$1
    local output=$2
    
    log_info "CSV转XML: $input -> $output"
    
    # 先转换为JSON,再转换为XML
    local temp_json=$(mktemp)
    
    if csv_to_json "$input" "$temp_json"; then
        json_to_xml "$temp_json" "$output"
        rm -f "$temp_json"
    else
        rm -f "$temp_json"
        return 1
    fi
}

# 格式化JSON
format_json() {
    local input=$1
    local output=$2
    
    log_info "格式化JSON: $input -> $output"
    
    if [ "$PRETTY_PRINT" = true ]; then
        python3 -m json.tool "$input" > "$output"
    else
        cat "$input" > "$output"
    fi
}

# 验证JSON
validate_json() {
    local input=$1
    
    log_info "验证JSON: $input"
    
    if python3 -m json.tool "$input" > /dev/null 2>&1; then
        log_info "JSON格式正确"
        return 0
    else
        log_error "JSON格式错误"
        return 1
    fi
}

# 验证XML
validate_xml() {
    local input=$1
    
    log_info "验证XML: $input"
    
    if xmllint --noout "$input" 2>/dev/null; then
        log_info "XML格式正确"
        return 0
    else
        log_error "XML格式错误"
        return 1
    fi
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] <输入格式>:<输出格式> <输入文件> [输出文件]"
    echo ""
    echo "选项:"
    echo "  -o <文件>        输出文件(默认: 自动生成)"
    echo "  -p               美化输出"
    echo "  -h               显示帮助信息"
    echo ""
    echo "支持的格式:"
    echo "  json   JSON格式"
    echo "  xml    XML格式"
    echo "  csv    CSV格式"
    echo "  yaml   YAML格式"
    echo ""
    echo "操作:"
    echo "  validate <格式> <文件>   验证文件格式"
    echo ""
    echo "示例:"
    echo "  $0 json:xml input.json output.xml"
    echo "  $0 xml:json input.xml output.json"
    echo "  $0 json:csv input.json output.csv"
    echo "  $0 csv:json input.csv output.json"
    echo "  $0 json:yaml input.json output.yaml"
    echo "  $0 -p json:xml input.json output.xml"
    echo "  $0 validate json input.json"
    echo "  $0 validate xml input.xml"
}

# 主函数
main() {
    # 解析选项
    while getopts "o:ph" opt; do
        case $opt in
            o)
                OUTPUT_FILE="$OPTARG"
                log_info "输出文件: $OUTPUT_FILE"
                ;;
            p)
                PRETTY_PRINT=true
                log_info "美化输出"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查参数
    if [ $# -eq 0 ]; then
        log_error "缺少参数"
        show_help
        exit 1
    fi
    
    # 检查是否为验证操作
    if [ "$1" = "validate" ]; then
        if [ $# -lt 3 ]; then
            log_error "验证操作需要格式和文件参数"
            show_help
            exit 1
        fi
        
        local format="$2"
        local file="$3"
        
        case $format in
            json)
                validate_json "$file"
                ;;
            xml)
                validate_xml "$file"
                ;;
            *)
                log_error "不支持的验证格式: $format"
                exit 1
                ;;
        esac
        
        exit 0
    fi
    
    # 解析格式转换
    local format_conversion="$1"
    
    if [[ ! "$format_conversion" =~ ^[a-z]+:[a-z]+$ ]]; then
        log_error "格式转换格式错误,应为: 输入格式:输出格式"
        show_help
        exit 1
    fi
    
    INPUT_FORMAT=$(echo "$format_conversion" | cut -d: -f1)
    OUTPUT_FORMAT=$(echo "$format_conversion" | cut -d: -f2)
    
    if [ $# -lt 2 ]; then
        log_error "缺少输入文件"
        show_help
        exit 1
    fi
    
    INPUT_FILE="$2"
    
    # 生成输出文件名
    if [ -z "$OUTPUT_FILE" ]; then
        local base_name=$(basename "$INPUT_FILE")
        local name_without_ext="${base_name%.*}"
        OUTPUT_FILE="${name_without_ext}.${OUTPUT_FORMAT}"
    fi
    
    # 检查输入文件
    if ! check_input_file; then
        exit 1
    fi
    
    # 执行转换
    case "${INPUT_FORMAT}:${OUTPUT_FORMAT}" in
        json:xml)
            json_to_xml "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        xml:json)
            xml_to_json "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        json:csv)
            json_to_csv "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        csv:json)
            csv_to_json "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        json:yaml)
            json_to_yaml "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        yaml:json)
            yaml_to_json "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        xml:csv)
            xml_to_csv "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        csv:xml)
            csv_to_xml "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        json:json)
            format_json "$INPUT_FILE" "$OUTPUT_FILE"
            ;;
        *)
            log_error "不支持的格式转换: ${INPUT_FORMAT}:${OUTPUT_FORMAT}"
            exit 1
            ;;
    esac
    
    log_info "转换完成: $OUTPUT_FILE"
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x data_converter.sh
  2. 基本用法:

    # JSON转XML
    ./data_converter.sh json:xml input.json output.xml
    
    # XML转JSON
    ./data_converter.sh xml:json input.xml output.json
    
    # JSON转CSV
    ./data_converter.sh json:csv input.json output.csv
    
    # CSV转JSON
    ./data_converter.sh csv:json input.csv output.json
    
    # JSON转YAML
    ./data_converter.sh json:yaml input.json output.yaml
    
    # YAML转JSON
    ./data_converter.sh yaml:json input.yaml output.json
  3. 高级用法:

    # 美化输出
    ./data_converter.sh -p json:xml input.json output.xml
    
    # 验证JSON格式
    ./data_converter.sh validate json input.json
    
    # 验证XML格式
    ./data_converter.sh validate xml input.xml
    
    # 格式化JSON
    ./data_converter.sh json:json input.json output.json

功能特点#

  • JSON与XML互转
  • JSON与CSV互转
  • JSON与YAML互转
  • XML与CSV互转
  • JSON格式化
  • 格式验证
  • 美化输出

依赖项#

  • python3: 用于数据转换
  • pyyaml: 用于YAML支持(可选)
  • xmllint: 用于XML验证(可选)

注意事项#

  1. 确保Python3已安装
  2. YAML转换需要安装pyyaml
  3. 大文件转换可能需要较长时间
  4. 某些复杂结构可能无法完美转换
  5. 确保输入文件格式正确