Shell脚本修改学生分组CSV时无法覆盖文件问题求助
为什么用
>覆盖原CSV文件会被清空? 这是shell重定向执行顺序导致的典型问题:shell会在执行你指定的命令(比如awk)之前,先处理重定向操作。
当你写awk ... ./alumnes.csv > ./alumnes.csv时,shell的动作是:
- 先打开
./alumnes.csv文件,直接截断它(也就是清空所有内容) - 然后才启动awk命令,让它去读取这个已经被清空的文件
- awk读取空内容后输出空,最终写入到已经被清空的文件里,结果就是文件彻底空了
而用>>追加的时候,shell是打开文件并把写入指针移到文件末尾,不会清空原内容,所以awk能正常读到原文件的所有内容,然后把处理后的内容追加到后面——但这显然不是你想要的,因为会导致文件里有重复的旧内容+新内容。
解决办法
1. 用临时文件过渡(最通用,所有环境都支持)
把awk的输出先写到一个临时文件,确认awk执行成功后,再替换原文件。修改脚本里的awk调用部分:
# 处理problemes的情况 awk -F';' -v OFS=';' -v id=$alumne -v new_group=$grupCanvi '{if($1==id)$3=new_group}1' ./alumnes.csv > ./temp_alumnes.csv && mv ./temp_alumnes.csv ./alumnes.csv # 处理practiques的情况同理 awk -F';' -v OFS=';' -v id=$alumne -v new_group=$grupCanvi '{if($1==id)$2=new_group}1' ./alumnes.csv > ./temp_alumnes.csv && mv ./temp_alumnes.csv ./alumnes.csv
这里的&&很重要:只有awk命令执行成功(返回值为0)时,才会执行mv替换原文件,避免因为awk出错导致原文件被空的临时文件覆盖。
2. 用GNU awk的就地编辑功能(简洁)
如果你用的是Linux系统,默认的awk是GNU awk(gawk),它支持-i inplace选项,可以直接修改原文件,内部会自动处理临时文件的逻辑:
# 处理problemes awk -i inplace -F';' -v OFS=';' -v id=$alumne -v new_group=$grupCanvi '{if($1==id)$3=new_group}1' ./alumnes.csv # 处理practiques同理 awk -i inplace -F';' -v OFS=';' -v id=$alumne -v new_group=$grupCanvi '{if($1==id)$2=new_group}1' ./alumnes.csv
这个方法不需要手动管理临时文件,代码更干净。
3. 用sponge工具(需要额外安装)
如果你能安装工具包,moreutils里的sponge命令专门解决这个问题:它会先把所有输入读入内存,再写入目标文件,这样就不会提前清空原文件。
# 先安装moreutils(Debian/Ubuntu) # sudo apt install moreutils # 处理problemes awk -F';' -v OFS=';' -v id=$alumne -v new_group=$grupCanvi '{if($1==id)$3=new_group}1' ./alumnes.csv | sponge ./alumnes.csv
额外小提示
看你的脚本和例子,还有个小问题:用户输入的分组类型是problem或practice(比如例子里的problems),但脚本里判断的是problemes和practiques(看起来是西班牙语/加泰罗尼亚语拼写),这会导致参数匹配失败,脚本不会执行修改逻辑,记得把判断条件和用户输入的参数统一起来哦!
内容的提问来源于stack exchange,提问作者Yeste
相关产品推荐
相关产品推荐

