Unix Shell脚本中含空格文件名引用及日期提取方案咨询
解决含空格文件名的循环读取与日期列插入问题
1. 修复循环读取完整文件名的问题
原来的for i in cat files.txt``会把空格、换行都当作字段分隔符,导致文件名被拆分。改用while read循环可正确读取每行完整文件名,推荐IFS= read -r filename的写法,确保保留文件名中的所有空格(包括首尾空格):
#!/bin/bash while IFS= read -r filename; do echo "当前处理文件:$filename" done < files.txt
2. 从文件名提取月份与年份并转换格式
通过参数扩展拆分文件名中的月份缩写和年份,再用关联数组映射月份缩写到数字格式:
#!/bin/bash # 定义月份缩写到数字的映射 declare -A month_map=( ["JAN"]="01" ["FEB"]="02" ["MAR"]="03" ["APR"]="04" ["MAY"]="05" ["JUN"]="06" ["JUL"]="07" ["AUG"]="08" ["SEP"]="09" ["OCT"]="10" ["NOV"]="11" ["DEC"]="12" ) while IFS= read -r filename; do # 去掉文件名的.txt后缀,得到"JAN 2021"格式的字符串 base_name=$(basename "$filename" .txt) # 拆分月份和年份 month_str="${base_name% *}" # 取空格前的部分(月份缩写) year="${base_name#* }" # 取空格后的部分(年份) # 获取对应的月份数字 month_num=${month_map[$month_str]} # 生成目标日期字符串,比如"2021-01"格式 date_str="${year}-${month_num}" echo "处理文件:$filename,对应日期:$date_str" done < files.txt
3. 插入日期列到文件每行
得到日期字符串后,使用awk或sed给目标文件的每行添加日期列,以下是两种实现方式:
方法1:用awk添加日期列(推荐,处理空格更稳定)
#!/bin/bash declare -A month_map=( ["JAN"]="01" ["FEB"]="02" ["MAR"]="03" ["APR"]="04" ["MAY"]="05" ["JUN"]="06" ["JUL"]="07" ["AUG"]="08" ["SEP"]="09" ["OCT"]="10" ["NOV"]="11" ["DEC"]="12" ) while IFS= read -r filename; do base_name=$(basename "$filename" .txt) month_str="${base_name% *}" year="${base_name#* }" month_num=${month_map[$month_str]} date_str="${year}-${month_num}" # 在每行开头插入日期(制表符分隔),临时文件替换原文件避免数据丢失 awk -v date="$date_str" '{print date "\t" $0}' "$filename" > "${filename}.tmp" && mv "${filename}.tmp" "$filename" done < files.txt
方法2:用sed添加日期列
若文件无特殊正则字符,可简化为sed命令:
# Linux环境 sed -i "s/^/${date_str}\t/" "$filename" # macOS环境(需加空参数) sed -i '' "s/^/${date_str}\t/" "$filename"
完整脚本示例
整合所有步骤,包含错误检查的最终脚本:
#!/bin/bash # 定义月份映射 declare -A month_map=( ["JAN"]="01" ["FEB"]="02" ["MAR"]="03" ["APR"]="04" ["MAY"]="05" ["JUN"]="06" ["JUL"]="07" ["AUG"]="08" ["SEP"]="09" ["OCT"]="10" ["NOV"]="11" ["DEC"]="12" ) # 检查files.txt是否存在 if [ ! -f "files.txt" ]; then echo "错误:files.txt不存在" exit 1 fi # 循环处理每个文件 while IFS= read -r filename; do # 检查文件是否存在 if [ ! -f "$filename" ]; then echo "警告:文件$filename不存在,跳过" continue fi base_name=$(basename "$filename" .txt) month_str="${base_name% *}" year="${base_name#* }" # 检查月份是否在映射中 if [ -z "${month_map[$month_str]}" ]; then echo "警告:无法识别月份$month_str,跳过文件$filename" continue fi month_num=${month_map[$month_str]} date_str="${year}-${month_num}" # 插入日期列到文件每行开头 awk -v date="$date_str" '{print date "\t" $0}' "$filename" > "${filename}.tmp" && mv "${filename}.tmp" "$filename" echo "已处理文件:$filename,添加日期列:$date_str" done < files.txt
内容的提问来源于stack exchange,提问作者DataFanatik
相关产品推荐
相关产品推荐

