如何通过给定 Linux 中另一个文件中的列从文件中删除列?

How to remove columns from a file by given the columns in anther file in Linux?

假设我有一个文件 A 包含需要删除的列号(我的输入文件文件 B 中确实有超过 500 列),

文件A:

2
5

我想从文件 B 中删除那些列(2 和 5):

a b c d e f
g h i j k l

在Linux中得到:

a c d f
g i j l

我该怎么办?我发现我可以使用以下代码消除打印这些列:

awk '{=="";print [=14=]}' fileB

然而,这种方式有两个问题,首先它并没有真正删除那些列,它只是使用空字符串来替换它们;其次,我不是手动输入这些列号,而是如何通过从另一个文件中读取来获取这些列号。


原问题: 假设我有一个文件 A 包含需要删除的列号,

文件A:

223
345
346
567

我想从 Linux 中的文件 B 中删除这些列 (223, 345,567),我该怎么办?

$ cat tst.awk
NR==FNR {
    badFldNrs[]
    next
}
FNR == 1 {
    for (inFldNr=1; inFldNr<=NF; inFldNr++) {
        if ( !(inFldNr in badFldNrs) ) {
            out2in[++numOutFlds] = inFldNr
        }
    }
}
{
    for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
        inFldNr = out2in[outFldNr]
        printf "%s%s", $inFldNr, (outFldNr<numOutFlds ? OFS : ORS)
    }
}

$ awk -f tst.awk fileA fileB
a c d f
g i j l

如果您的 cut--complement 选项,那么您可以:

cut --complement -d ' ' -f "$(echo $(<FileA))" fileB

一个awk想法:

awk '
FNR==NR { skip[] ; next }                # store field #s to be skipped
        { line=""                          # initialize output variable
          pfx=""                           # first prefix will be ""
          for (i=1;i<=NF;i++)              # loop through the fields in this input line ...
              if ( !(i in skip) ) {        # if field # not mentioned in the skip[] array then ...
                 line=line pfx $i          # add to our output variable
                 pfx=OFS                   # prefix = OFS for 2nd-nth fields to be added to output variable
              }
          if ( pfx == OFS )                # if we have something to print ...
             print line                    # print output variable to stdout
         }
' fileA fileB

注意: OP 没有提供 input/output 字段分隔符; OP 可以根据需要添加适当的 FS/OFS 分配

这会生成:

a c d f
g i j l

使用awk

$ awk 'NR==FNR {col[]=;next} {for(i=1;i<=NF;++i) if (i != col[i]) printf("%s ", $i);  printf("\n")}' fileA fileB
a c d f
g i j l