如何合并三个Bash命令优化文本转CSV及数据清理操作?
问题:整合PLINK文本转CSV的多步Bash命令
我有一个.txt文件,目前用三个sed命令处理:
- 将制表符替换为逗号,转成.csv文件(命令A)
- 删除前8行(命令B)
- 移除第9行开头的
#(命令C)
原命令如下:
# 命令A:制表符转逗号,输出为CSV sed 's/\t/,/g' individuals/$message/$message.txt > individuals/$message/$message.csv # 命令B:删除CSV文件前8行 sed -i 1,8d individuals/$message/$message.csv # 命令C:移除第9行(现在是第一行)开头的# 和空格 sed -i 's/.\{2\}//' individuals/$message/$message.csv
需求:有没有更优方案,比如整合成单一命令?不限制必须用sed,只要是Bash命令实现。
附数据示例(原.txt文件内容):
# This data file generated by PLINK at: Mon Jul 11 16:18:56 2022 # # Below is a text version of your data. Fields are TAB-separated. # Each line corresponds to a single SNP. For each SNP, we provide its # identifier, its location on a reference human genome, and the genotype call. # For further information (e.g. which reference build was used), consult the # original source of your data. # # rsid chromosome position genotype 22:16050607G-A 22 16050607 GG
注:第9行(# rsid chromosome...)需要保留,仅移除开头的# 。
优化方案:单命令完成所有处理
可以用sed单命令或者awk实现,只需要一次读取原文件,直接输出处理后的CSV,避免多次读写文件的开销。
方案1:使用sed单命令
sed -n '9,$s/\t/,/g; 9s/^# //; 9,$p' individuals/$message/$message.txt > individuals/$message/$message.csv
命令解释:
-n:默认不输出任何行,仅执行指定的输出操作9,$s/\t/,/g:对第9行到最后一行,将所有制表符替换为逗号9s/^# //:仅针对第9行,精准替换开头的#为空(比s/.\{2\}//更安全,避免误删其他字符)9,$p:输出第9行到最后一行的处理结果
方案2:使用awk(可读性更强)
awk 'NR>8 { if(NR==9) sub(/^# /, "") gsub(/\t/, ",") print }' individuals/$message/$message.txt > individuals/$message/$message.csv
命令解释:
NR>8:仅处理第9行及以后的内容(NR是awk内置变量,表示当前行号)if(NR==9) sub(/^# /, ""):如果是第9行,移除开头的#gsub(/\t/, ","):将当前行的所有制表符替换为逗号print:输出处理后的行
优于原方案的点:
- 减少IO开销:原方案需要三次读写文件,优化后仅一次读取原文件、一次写入结果文件,效率更高
- 匹配更精准:用
^#精准定位开头的注释,避免原命令中s/.\{2\}//可能误删非目标字符的风险 - 操作更简洁:单命令完成所有处理,减少命令行输入的繁琐
内容的提问来源于stack exchange,提问作者Igor Salerno Filgueiras
相关产品推荐
相关产品推荐

