求助:编写Bash脚本下载RSS Feed并保存为独立HTML文件失败,求排查错误
修复Bash RSS下载脚本的问题
原脚本的核心错误
- 正则表达式转义错误:代码里的
(?<=是HTML转义后的<,实际Bash环境中需要用(?<=),否则grep的Perl正则引擎无法识别,直接导致匹配失败。 - RSS结构解析逻辑错误:HN的RSS中,每个条目是
<item>节点,<title>和<description>是同级节点,并非<description>包含<title>,原脚本的提取逻辑完全颠倒。 - 未处理文件名特殊字符:标题中包含的空格、
/、?等字符会导致创建文件时报错,必须清理或转义。 read命令行为问题:默认while read会截断换行、压缩空格,需要用IFS= read -r来保留内容完整性。- 冗余管道处理:多次重复用sed和grep处理标签,逻辑混乱且效率低下。
推荐修正方案(使用XML专用解析工具)
用xmlstarlet(需提前安装,如apt install xmlstarlet或brew install xmlstarlet)解析RSS,这是处理XML/RSS最可靠的方式:
#!/bin/bash RSS_URL="https://news.ycombinator.com/rss" OUTPUT_DIR="hn_articles" # 创建输出目录,避免报错 mkdir -p "$OUTPUT_DIR" # 解析RSS,提取每个item的标题和描述,用分隔符分隔 xmlstarlet sel -t -m "/rss/channel/item" -v "title" -o "|||" -v "description" -n "$RSS_URL" | while IFS="|||" read -r title description; do # 清理标题中的非法文件名字符,替换为下划线 safe_title=$(echo "$title" | sed 's/[\/:*?"<>|]/_/g' | tr -s '_') filename="${OUTPUT_DIR}/${safe_title}.html" # 仅当文件不存在时创建 if [ ! -f "$filename" ]; then # 生成标准HTML结构 echo "<!DOCTYPE html><html><head><title>$title</title></head><body>$description</body></html>" > "$filename" echo "Created: $filename" fi done
无XML工具的替代方案(基于grep/sed)
如果无法安装xmlstarlet,可以用以下改进版脚本(依赖RSS格式规整,标签不跨过多换行):
#!/bin/bash RSS_URL="https://news.ycombinator.com/rss" OUTPUT_DIR="hn_articles" TMP_FILE="/tmp/hn_rss.tmp" mkdir -p "$OUTPUT_DIR" # 静默下载RSS到临时文件 curl -L -s "$RSS_URL" > "$TMP_FILE" # 遍历每个item的标题和描述 grep -A 2 "<item>" "$TMP_FILE" | while IFS= read -r line; do if [[ "$line" =~ "<title>" ]]; then # 提取标题内容 title=$(echo "$line" | sed 's/.*<title>//;s/<\/title>.*//') elif [[ "$line" =~ "<description>" ]]; then # 提取描述内容 description=$(echo "$line" | sed 's/.*<description>//;s/<\/description>.*//') # 处理合法文件名 safe_title=$(echo "$title" | sed 's/[\/:*?"<>|]/_/g' | tr -s '_') filename="${OUTPUT_DIR}/${safe_title}.html" if [ ! -f "$filename" ]; then echo "<!DOCTYPE html><html><head><title>$title</title></head><body>$description</body></html>" > "$filename" echo "Created: $filename" fi # 重置变量,避免污染下一个条目 title="" description="" fi done # 清理临时文件 rm "$TMP_FILE"
内容的提问来源于stack exchange,提问作者zeddie
相关产品推荐
相关产品推荐

