有没有办法完全删除awk中的字段,以便不打印额外的分隔符?

时间:2012-05-21 22:42:51

标签: awk gawk

请考虑以下命令:

gawk -F"\t" "BEGIN{OFS=\"\t\"}{$2=$3=\"\"; print $0}" Input.tsv

当我设置$ 2 = $ 3 =“”时,达到与写作相同效果的预期效果:

print $1,$4,$5...$NF

然而,实际发生的是我得到两个空字段,额外的字段分隔符仍在打印。

是否可以实际删除$ 2和$ 3?

注意:如果这是在bash的Linux上,则上面的正确语句如下,但Windows在cmd.exe中没有很好地处理单引号。

gawk -F'\t' 'BEGIN{OFS="\t"}{$2=$3=""; print $0}' Input.tsv

9 个答案:

答案 0 :(得分:7)

您无法删除中间的字段,但可以通过递减NF来删除最后的字段。

因此,您可以将所有后面的字段向下移动以覆盖$2$3,然后将NF减少2,这将删除最后两个字段:

$ echo 1 2 3 4 5 6 7 | awk '{for(i=2; i<NF-1; ++i) $i=$(i+2); NF-=2; print $0}'
1 4 5 6 7

答案 1 :(得分:7)

这是一个老人但很有礼貌。

正如Jonathan所指出的,你不能删除中间的字段,但你可以用其他字段的内容替换它们的内容。并且您可以创建一个可重用的函数来为您处理删除。

$ cat test.awk
function rmcol(col,     i) {
  for (i=col; i<NF; i++) {
    $i=$(i+1)
  }
  NF--
}

{
  rmcol(3)
}

1

$ printf 'one two three four\ntest red green blue\n' | awk -f test.awk
one two four
test red blue

答案 2 :(得分:3)

如果您只想删除列,可以使用cut

cut -f 1,4- file.txt

模仿cut

awk -F "\t" '{ for (i=1; i<=NF; i++) if (i != 2 && i != 3) { if (i == NF) printf $i"\n"; else printf $i"\t" } }' file.txt

类似:

awk -F "\t" '{ delim =""; for (i=1; i<=NF; i++) if (i != 2 && i != 3) { printf delim $i; delim = "\t"; } printf "\n" }' file.txt

HTH

答案 3 :(得分:1)

一种方法是删除您执行的字段,并使用gsub删除多余的空格:

awk 'BEGIN { FS = "\t" } { $2 = $3 = ""; gsub( /\s+/, "\t" ); print }' input-file

答案 4 :(得分:1)

在自杀史蒂夫的回答中,我想建议一个更多的解决方案但是使用sed而不是awk。

这似乎比史蒂夫建议的切割更复杂。但这是更好的解决方案,因为sed -i允许就地编辑。

sed -i 's/\(.*,\).*,.*,\(.*\)/\1\2/' FILENAME

答案 5 :(得分:1)

我认为在不使用循环的情况下在Awk中执行此操作的唯一方法是使用gsub上的$0来组合相邻的FS

$ echo {1..10} | awk '{$2=$3=""; gsub(FS"+",FS); print}'
1 4 5 6 7 8 9 10

答案 6 :(得分:0)

好吧,如果目标是删除额外的分隔符,那么你可以在Linux上使用“tr”。例如:

$ echo“1,2 ,,, 5”| tr -s','

1,2,5-

答案 7 :(得分:0)

answer of ghoti中介绍的方法存在一些问题:

  • 每次分配$i = $(i+1)都会强制awk重建记录$0。这意味着如果您有100个字段,并且要删除字段10,则将记录重建90次。

  • 手动更改NF的值不符合posix,并导致不确定的行为(如注释中所述)。

删除一组列比较麻烦但稳定的鲁棒方式是:

单列:

awk -v del=3 '
    BEGIN{FS=fs;OFS=ofs}
    { b=""; for(i=1;i<=NF;++i) if(i!=del) b=(b?b OFS:"") $i; $0=b }
    # do whatever you want to do
   ' file

多列:

awk -v del=3,5,7 '
    BEGIN{FS=fs;OFS=ofs; del="," del ","}
    { b=""; for(i=1;i<=NF;++i) if (del !~ ","i",") b=(b?b OFS:"") $i; $0=b }
    # do whatever you want to do
   ' file

答案 8 :(得分:-1)

echo one two three four five six|awk '{
print $0
is3=$3
$3=""
print $0
print is3
}'
一二三四五六

一二四五六

3