使用 bash 创建包含数据中现有列的子字符串的新列

create new column containing a substring of an existing column in data using bash

我有一个大 tsv.gz 文件 (40GB),我想从现有变量 col3 中提取一个字符串,将其存储在新变量 New_var 中(放置在开头)并将所有内容保存到新文件中。 数据示例“old_file.tsv.gz”

col1  col2  col3  col4
1  positive  12:1234A  100
2  negative  10:9638B  110
3  positive  5:0987A  100
4  positive  8:5678A  170

所需数据“new_file.tsv.gz”

New_var  col1  col2  col3  col4
12  1  positive  12:1234A  100
10  2  negative  10:9638B  110
5  3  positive  5:0987A  100
8  4  positive  8:5678A  170

我是 bash 的新人,所以我尝试了很多东西但我卡住了,我已经尝试了

zcat old_file.tsv.gz | awk '{print New_var=,[=13=] }' | awk ' ~ /^[0-9]:/{print [=13=] | (gzip -c > new_file.tsv.gz) }'

我想我有很多问题。 {print New_var=,[=16=] } 确实创建了 col3 的副本,但没有重命名。然后,当我添加代码的最后一部分时 awk ' ~ /^[0-9]:/{print [=18=] | (gzip -c > new_file.tsv.gz) }'... 什么也没有出现(我试图查看是否忘记了括号但找不到问题)。 另外我不确定这种方式是否是最好的方式。 知道如何让它发挥作用吗?

在单独的文件中制作一个 AWK 脚本(为了便于阅读),比如 1.awk:

{ if (NR > 1) { 
    # all data lines 
    split(, a, ":");  
    print a[1], , , , ; 
  } else {
    # header line
    print "new_var", , , , ;
  } 
}

现在用 AWK 文件处理输入(比如 1.csv.gz):

zcat 1.csv.gz | awk -f 1.awk | gzip -c > 1_new.csv.gz

我建议使用一个制表符 (\t) 和 : 作为输入字段分隔符:

awk 'BEGIN { FS="[\t:]"; OFS="\t" }
     NR==1 { ="New_var" OFS  }
     NR>1  { [=10=]= OFS [=10=] }
     { print }'

作为一行:

awk 'BEGIN{ FS="[\t:]"; OFS="\t" } NR==1{ ="New_var" OFS  } NR>1{ [=11=]= OFS [=11=] } { print }'

参见:8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR