change.sh 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/bin/bash
  2. # 文本文件转C头文件脚本
  3. # 支持中文和特殊字符
  4. # 用法: ./text_to_header.sh <输入文件> <输出头文件> <变量名>
  5. set -e
  6. # 显示颜色输出
  7. RED='\033[0;31m'
  8. GREEN='\033[0;32m'
  9. YELLOW='\033[1;33m'
  10. NC='\033[0m' # No Color
  11. # 显示用法信息
  12. show_usage() {
  13. echo -e "${GREEN}用法: $0 <输入文件> <输出头文件> <变量名>${NC}"
  14. echo -e "${GREEN}示例: $0 input.txt text_data.h my_text${NC}"
  15. exit 1
  16. }
  17. # 检查工具是否安装
  18. check_tools() {
  19. local tools=("hexdump" "sed" "awk" "basename" "wc" "file")
  20. for tool in "${tools[@]}"; do
  21. if ! command -v "$tool" &> /dev/null; then
  22. echo -e "${RED}错误: 未找到工具 $tool${NC}"
  23. exit 1
  24. fi
  25. done
  26. }
  27. # 检查参数
  28. if [ $# -ne 3 ]; then
  29. show_usage
  30. fi
  31. INPUT_FILE="$1"
  32. OUTPUT_FILE="$2"
  33. VAR_NAME="$3"
  34. # 检查输入文件
  35. if [ ! -f "$INPUT_FILE" ]; then
  36. echo -e "${RED}错误: 输入文件 '$INPUT_FILE' 不存在!${NC}"
  37. exit 1
  38. fi
  39. # 检查文件编码
  40. FILE_ENCODING=$(file -b --mime-encoding "$INPUT_FILE")
  41. if [[ "$FILE_ENCODING" != "utf-8" && "$FILE_ENCODING" != "us-ascii" ]]; then
  42. echo -e "${YELLOW}警告: 文件编码为 $FILE_ENCODING,建议使用UTF-8编码${NC}"
  43. fi
  44. # 获取文件信息
  45. FILENAME=$(basename "$INPUT_FILE")
  46. FILE_SIZE=$(wc -c < "$INPUT_FILE")
  47. TEXT_SIZE=$(wc -m < "$INPUT_FILE")
  48. echo -e "${GREEN}正在处理文件: $INPUT_FILE${NC}"
  49. echo -e "文件大小: $FILE_SIZE 字节"
  50. echo -e "文本长度: $TEXT_SIZE 字符"
  51. echo -e "编码: $FILE_ENCODING"
  52. # 创建头文件
  53. create_header() {
  54. # 创建头文件头部
  55. cat > "$OUTPUT_FILE" << EOF
  56. /* 自动生成的文本数据头文件 */
  57. /* 源文件: $FILENAME */
  58. /* 文件大小: $FILE_SIZE 字节 */
  59. /* 生成时间: $(date +"%Y-%m-%d %H:%M:%S") */
  60. /* 编码: $FILE_ENCODING */
  61. #ifndef ${VAR_NAME^^}_H
  62. #define ${VAR_NAME^^}_H
  63. #include <stddef.h>
  64. // 文本数据(UTF-8编码)
  65. const char *${VAR_NAME} =
  66. EOF
  67. # 使用hexdump处理文件内容
  68. echo "正在转换文本内容..."
  69. # 临时文件用于处理转义
  70. TEMP_FILE=$(mktemp)
  71. # 读取文件并处理转义字符
  72. while IFS= read -r line || [ -n "$line" ]; do
  73. # 转义特殊字符
  74. line=$(printf "%s" "$line" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed 's/^/"/' | sed 's/$/\\n"/')
  75. echo " $line" >> "$TEMP_FILE"
  76. done < "$INPUT_FILE"
  77. # 移除最后一行的换行符
  78. sed -i '$ s/\\n"$/"/' "$TEMP_FILE"
  79. # 将处理后的内容添加到头文件
  80. cat "$TEMP_FILE" >> "$OUTPUT_FILE"
  81. # 清理临时文件
  82. rm -f "$TEMP_FILE"
  83. # 完成头文件
  84. cat >> "$OUTPUT_FILE" << EOF
  85. ;
  86. // 文本数据大小(包括null终止符)
  87. const size_t ${VAR_NAME}_size = $((FILE_SIZE + 1));
  88. // 文本长度(字符数)
  89. const size_t ${VAR_NAME}_length = $TEXT_SIZE;
  90. #endif /* ${VAR_NAME^^}_H */
  91. EOF
  92. echo -e "${GREEN}成功生成头文件: $OUTPUT_FILE${NC}"
  93. }
  94. # 创建示例C文件
  95. create_example_c() {
  96. local example_file="${OUTPUT_FILE%.h}_example.c"
  97. local base_header=$(basename "$OUTPUT_FILE")
  98. cat > "$example_file" << EOF
  99. #include <stdio.h>
  100. #include <string.h>
  101. #include <locale.h>
  102. #include "$base_header"
  103. int main() {
  104. // 设置locale以支持中文输出
  105. setlocale(LC_ALL, "zh_CN.UTF-8");
  106. printf("=== 文本数据测试程序 ===\\n");
  107. printf("文件: %s\\n", "$FILENAME");
  108. printf("编码: %s\\n", "$FILE_ENCODING");
  109. printf("\\n");
  110. printf("文本内容:\\n");
  111. printf("----------------------------------------\\n");
  112. printf("%s", ${VAR_NAME});
  113. printf("----------------------------------------\\n");
  114. printf("\\n");
  115. printf("统计信息:\\n");
  116. printf("数组大小: %zu 字节\\n", ${VAR_NAME}_size);
  117. printf("文本长度: %zu 字符\\n", ${VAR_NAME}_length);
  118. printf("字符串长度: %zu 字节\\n", strlen(${VAR_NAME}));
  119. printf("\\n");
  120. printf("十六进制查看(前64字节):\\n");
  121. for (size_t i = 0; i < ${VAR_NAME}_size && i < 64; i++) {
  122. printf("%02x ", (unsigned char)${VAR_NAME}[i]);
  123. if ((i + 1) % 16 == 0) printf("\\n");
  124. }
  125. printf("\\n");
  126. return 0;
  127. }
  128. EOF
  129. echo -e "${GREEN}创建示例C文件: $example_file${NC}"
  130. }
  131. # 创建编译脚本
  132. create_build_script() {
  133. local build_script="build_${VAR_NAME}.sh"
  134. local program_name="${VAR_NAME}_program"
  135. cat > "$build_script" << EOF
  136. #!/bin/bash
  137. # 自动编译脚本
  138. echo -e "\033[0;32m编译程序...\033[0m"
  139. gcc -Wall -std=c99 -o "$program_name" "${OUTPUT_FILE%.h}_example.c"
  140. if [ \$? -eq 0 ]; then
  141. echo -e "\033[0;32m编译成功!\033[0m"
  142. echo -e "\033[0;33m运行程序: ./$program_name\033[0m"
  143. else
  144. echo -e "\033[0;31m编译失败!\033[0m"
  145. exit 1
  146. fi
  147. EOF
  148. chmod +x "$build_script"
  149. echo -e "${GREEN}创建编译脚本: $build_script${NC}"
  150. }
  151. # 显示文件预览
  152. show_preview() {
  153. echo -e "${YELLOW}文件预览(前10行):${NC}"
  154. head -10 "$INPUT_FILE"
  155. echo -e "${YELLOW}...${NC}"
  156. }
  157. # 主执行流程
  158. main() {
  159. check_tools
  160. show_preview
  161. create_header
  162. create_example_c
  163. create_build_script
  164. echo -e "${GREEN}========================================${NC}"
  165. echo -e "${GREEN}完成! 接下来可以:${NC}"
  166. echo -e "1. 查看头文件: ${YELLOW}cat $OUTPUT_FILE${NC}"
  167. echo -e "2. 编译程序: ${YELLOW}./build_${VAR_NAME}.sh${NC}"
  168. echo -e "3. 运行程序: ${YELLOW}./${VAR_NAME}_program${NC}"
  169. echo -e "${GREEN}========================================${NC}"
  170. }
  171. # 执行主函数
  172. main