【问题标题】:awk: delete the lines with the same first field after a matchawk:匹配后删除具有相同第一个字段的行
【发布时间】:2015-04-26 23:02:13
【问题描述】:

(更新示例和解决方案)数据按第一个字段顺序分组。每个第一个字段的行数是可变的。找到匹配(不受欢迎的关键字)后,需要删除与匹配的第一个字段相同的行。

输入是:

1  orange  dog    red
1  apple   cat    green
2  peach   frog   grey
3  apple  lamb   white
3  orange  lamb   white
3  mango   cat    yellow
3  apple   mouse  blue

如果匹配“cat”或“orange”,则删除具有相同第一个字段(“1”或“3”)的行。输出将是:

2  peach   frog   grey

解决方案来自科斯塔斯:

awk 'NR==FNR{if($0~/cat|orange/)L[$1]=1;next} !($1 in L)' test1.txt test1.txt

【问题讨论】:

  • 这看起来像是一道作业题。你试过什么了?它必须是一个 awk 解决方案吗?看起来您需要“两次传递”数据,因为在读取所有记录之前您不会知道是否发生匹配。
  • "3 apple mouse blue" 为什么不呢? ....因为 3 在第一列
  • 我认为是因为3 mango cat yellow 包含不允许的关键字。
  • Awk 是我(几乎不)知道的唯一语言,我尝试只用 awk 完成我的项目。

标签: awk


【解决方案1】:
awk '
# pass input 1 time to find all occurence of "cat"
NR==FNR{
    if( $0~/cat/)
        L[$1]=1 # add founded 1st field into array L
    next
       }
# for second pass print line if value of 1st field is not in array L
!($1 in L)' input input 

【讨论】:

  • 由于我对 awk 的经验非常有限,如果您能提供我可以测试的完整命令行,我将不胜感激。
  • 根据您的脚本,我尝试了以下命令,但总是收到错误消息。 awk 'NR==FNR{if($0~/(cat|orange)/){L[$1]=1;next} !($1 in L) {print $0}' test1.txt test1.txt 错误信息是awk: syntax error at source line 1 context is NR==FNR{if($0~/(cat|orange)/){L[$1]=1;next} !($1 in L) >>> { <<< awk: illegal statement at source line 1 awk: illegal statement at source line 1 missing }
  • @DonXu 你必须在orange)/){L[$1] 中删除额外的{ 正确的行是NR==FNR{if($0~/cat|orange/)L[$1]=1;next} !($1 in L)' test1.txt test1.txt
【解决方案2】:

如果该行与术语匹配,并且第一列未包含在字典 f 中,则打印

awk '{
  if($0!~/(cat|orange)/){ 
    if(!($1 in f)){
      print $0;
    }
  }else{ 
    f[$1]=1
  }
}' input

【讨论】:

  • @AlexA。我正在等待 OP 的回复.....因为如果它不起作用我可以删除.....
  • 我又试了一次,成功了! (我打错字了)非常感谢!
  • 我原来的例子不是最好的。因为,如果不受欢迎的关键字不在第一行:(参见上面的示例#2),第一个不受欢迎的关键字之前的行将被遗漏。 Jose,您的脚本将在示例 #2 中返回“2 peach frog gray 3 apple lamb white”。
  • @DonXu 那么,Costas 的解决方案更好
【解决方案3】:

如果非 awk 的答案是可以的,在 perl 中我会这样做:

use strict;
use warnings;

my @disallowed_keywords = qw ( cat orange );

my %records;
my %ids_to_reject;

my $reject_regex = join( "|", @disallowed_keywords );
$reject_regex = qr/$reject_regex/;

while ( my $line = <DATA> ) {
    my ($id) = split( ' ', $line );
    push( @{ $records{$id} }, $line );
    if ( $line =~ $reject_regex ) { $ids_to_reject{$id}++ }
}

foreach my $id ( sort keys %records ) {
    if ( not $ids_to_reject{$id} ) {
        print join( "\n", @{ $records{$id} } ), "\n";
    }
}

__DATA__ 
1  orange  dog    red
1  apple   cat    green
2  peach   frog   grey
3  orange  lamb   white
3  mango   cat    yellow
3  apple   mouse  blue

【讨论】:

  • 感谢您的意见。但 awk 是我唯一知道的(几乎不知道)。
  • 我不会对选择提出异议,但我会指出 - awk 非常强大,但适用于特定任务 - 虽然 perl 以难以阅读而闻名,awk可能会更糟!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 2011-07-04
  • 1970-01-01
  • 2012-09-19
相关资源
最近更新 更多