腳本一:單文件處理版 (del_comment.sh)
#!/bin/bash
# 用法: ./del_comment.sh source_file [target_file]
if [ -z "$1" ]; then
echo "Usage: $0 source_file [target_file]"
exit 1
fi
src="$1"
ext="${src##*.}" # 獲取後綴
if [ -n "$2" ]; then
dst="$2"
else
dst="${src%.*}.temp" # 默認同名 .temp
fi
touch "$dst"
case "$ext" in
sh)
echo "Processing shell script..."
# 刪除行首 # 註釋、行內 # 註釋、空行
sed 's/[[:space:]]#.*//g' "$src" | \
sed '/^#/d' | \
sed '/^[[:space:]]*$/d' > "$dst"
;;
c|java)
echo "Processing C/Java source..."
# 刪除 /* */ 單行註釋、跨行註釋、// 註釋、空行
sed 's/\/\*.*\*\///g' "$src" | \
sed '/\/\*/,/.*\*\//d' | \
sed 's/\/\/.*//g' | \
sed '/^[[:space:]]*$/d' > "$dst"
;;
*)
echo "Unknown file type: $ext"
rm -f "$dst"
exit 1
;;
esac
echo "Source: $src -> Target: $dst"
腳本二:遞歸目錄處理版 (del_comment_recursive.sh)
#!/bin/sh
# 遞歸處理目錄下所有 .c/.cpp/.h 文件
del_comment_file() {
# 刪除 // 開頭的行
sed -i '/^[[:space:]]*\/\//d' "$file"
# 刪除行尾 // 註釋 (保留字符串中的 //)
sed -i 's/\/\/[^"]*//' "$file"
# 刪除單行 /* */ 註釋
sed -i 's/\/\*.*\*\///' "$file"
# 刪除跨行 /* */ 註釋
sed -i '/^[[:space:]]*\/\*/,/.*\*\//d' "$file"
}
del_comment() {
for file in *; do
case "$file" in
*.c|*.cpp|*.h)
del_comment_file
;;
*)
if [ -d "$file" ]; then
cd "$file"
del_comment
cd ..
fi
;;
esac
done
}
if [ ! -e "$1" ]; then
echo "Directory not exist: $1"
exit 1
fi
cd "$1"
del_comment
核心 sed 正則解析
| 模式 | 含義 | 適用場景 |
s/[[:space:]]#.*//g | 刪除行內 # 及其後內容 | Shell/Python 註釋 |
/^#/d | 刪除以 # 開頭的行 | Shell 整行註釋 |
s/\/\*.*\*\///g | 刪除單行 /* ... */ | C/C++/Java 單行塊註釋 |
/\/\*/,/.*\*\//d | 刪除跨行 /* ... */ 區間 | C/C++/Java 多行塊註釋 |
s/\/\/.*//g | 刪除 // 及其後內容 | C++/Java 行註釋 |
/^[[:space:]]*$/d | 刪除空白行 | 通用清理 |
局限性與改進方向
- 字符串誤傷:
printf("https://example.com"); 中的 // 會被誤刪。改進:先提取字符串字面量佔位,處理完再還原。
- 嵌套塊註釋:C 標準不支持嵌套,但某些編譯器允許,簡單正則無法正確配對。
- 多語言擴展:可按後綴分派不同處理函數,支持 Python (
#)、HTML (<!-- -->)、SQL (--//* */) 等。
- 保留文檔註釋:如 Javadoc (
/** */)、Doxygen,可添加保留邏輯。
工業級替代方案
uncrustify、clang-format:格式化同時可配置註釋處理。
doxygen -x 提取文檔註釋而非刪除。
- 語言專用工具:
stripcmt (C)、comment-remover (npm/JS)。