如何从TSV文件填充Shell脚本模板并生成对应命名的新文件
需求说明
我有一个包含100条记录的data.tsv文件,结构如下:
| ColumnA | ColumnB | ColumnC | ColumnD | ColumnE |
|---|---|---|---|---|
| Cell 31 | Cell 4 | Cell 3 | Cell 5 | Cell 8 |
| Cell 21 | Cell 2 | Cell 5 | Cell 6 | Cell 9 |
同时有一个template.in脚本模板,需要将TSV文件中的对应列值填充到模板的变量位置:
for_example = $ColumnA testmyhpothesis = $ColumnB $ColumnC cleandir = $ColumnD $ColumnE testOutdir = /path/todir/$ColumnD
要求以TSV文件第一列的单元格值为文件名生成新脚本文件,示例如下:
- 文件
Cell 31.in内容:
for_example = Cell 31 testmyhpothesis = Cell 4 Cell 3 cleandir = Cell 5 Cell 8 testOutdir = /path/todir/Cell 5
- 文件
Cell 21.in内容:
for_example = Cell 21 testmyhpothesis = Cell 2 Cell 5 cleandir = Cell 6 Cell 9 testOutdir = /path/todir/Cell 6
我尝试的awk命令未实现需求:
awk -F '\t' '{for (i = 2; i <= NF; i++) {print $i >> new_file} data.tsv
求正确的实现方法。
正确实现方法
可以用awk完成这个需求,核心逻辑是先建立TSV列名与列索引的映射,再逐行读取数据并替换模板中的变量,最终生成目标文件。
完整命令如下:
awk -F '\t' ' BEGIN { # 预读取模板文件内容 while ((getline line < "template.in") > 0) { template = template line "\n" } close("template.in") } NR == 1 { # 构建列名到列号的映射表 for (i = 1; i <= NF; i++) { col_map[$i] = i } next } { # 复制模板内容用于替换 content = template # 替换所有变量为对应列的值 for (col in col_map) { gsub("$" col, $(col_map[col]), content) } # 生成目标文件名 filename = $1 ".in" # 写入文件并关闭 print content > filename close(filename) } ' data.tsv
关键步骤说明:
- 预读模板:在
BEGIN块中一次性读取template.in的全部内容,避免重复IO操作,提升效率。 - 表头映射:处理TSV的第一行(表头),将每个列名与对应的列索引存入数组,方便后续快速查找对应值。
- 变量替换:对每一行数据,复制模板内容后,用
gsub将所有$ColumnX格式的变量替换为当前行对应列的实际值。 - 文件生成:以TSV第一列的值作为文件名(添加
.in后缀),将替换后的内容写入文件,写完后立即关闭文件,避免系统文件句柄耗尽。
注意事项:
- 如果TSV第一列包含空格、斜杠等特殊字符,部分系统可能无法识别这类文件名,可根据需求对文件名做处理(例如将空格替换为下划线:
gsub(/ /, "_", $1)后再生成文件名)。 - 确保
template.in和data.tsv位于当前工作目录,或在命令中指定完整文件路径。
内容的提问来源于stack exchange,提问作者devbasic
相关产品推荐
相关产品推荐

