Bash:使用 cut 提取列并进一步过滤一列

Bash: extract columns with cut and filter one column further

我有一个制表符分隔的文件,想用 cut 提取几列。

两个示例行

(...)
0    0    1    0    AB=1,2,3;CD=4,5,6;EF=7,8,9    0    0
1    1    0    0    AB=2,1,3;CD=1,1,2;EF=5,3,4    0    1
(...)

我想要实现的是 select 第 2、3、5 和 7 列,但是仅来自第 5 列 CD=4,5,6

所以我的预期结果是

0    1    CD=4,5,6;    0
1    0    CD=1,1,2;    1

如何使用 cut 来解决这个问题,并在其中一个提取的列上使用 运行 grep?任何其他单线当然也可以。

使用 awk 更容易完成。使用 ; 作为分隔符拆分第 5 个字段,然后打印第二个子字段。

awk 'BEGIN {FS="\t"; OFS="\t"} 
     {split(, a, ";"); print , , a[2]";",  }' inputfile > outputfile

如果要打印以 CD= 开头的子字段,请使用循环:

awk 'BEGIN {FS="\t"; OFS="\t"} 
     {n = split(, a, ";");
      for (i = 1; i <= n; i++) {
        if (a[i] ~ /^CD=/) subfield = a[i];
      }
      print , , subfield";", }' < inputfile > outputfile

这是另一个awk

$ awk -F'\t|;' -v OFS='\t' '{print ,,,$NF}' file

0       1       CD=4,5,6        0
1       0       CD=1,1,2        1

或与cut/paste

$ paste <(cut -f2,3 file) <(cut -d';' -f2 file) <(cut -f7 file)

0       1       CD=4,5,6        0
1       0       CD=1,1,2        1

我认为 awk 是完成此类任务的最佳工具,另外两个答案为您提供了很好的简短解决方案。

我想指出的是,您可以使用 awk's 内置的拆分工具在解析输入时获得更大的灵活性。这是一个使用隐式拆分的示例脚本:

parse.awk

# Remember second, third and seventh columns
{
  a = 
  b = 
  d = 
}

# Split the fifth column on ";". After this the positional variables
# (e.g. , # , ..., $NF) contain the fields from the previous
# fifth column
{
  oldFS = FS
  FS    = ";"
  [=10=]    = 
}

# For example to test if the second elemnt starts with "CD", do 
# something like this
 ~ /^CD/ {
  c = 
}

# Print the selected elements
{
  print a, b, c, d
}

# Restore FS
{
  FS = oldFS
}

运行 像这样:

awk -f parse.awk FS='\t' OFS='\t' infile

输出:

0   1   CD=4,5,6    0
1   0   CD=1,1,2    1