如何通过给定 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
假设我有一个文件 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