试图从动态 NF 文件中获取最后 4 个不同的值

trying to get last 4 distinct values from a dynamic NF file

我需要从文件中的每条记录中获取最后 4 个唯一值。文件以逗号分隔,不同记录的列数可以不同。我的输入文件。

$ cat last_cols.txt
F
F,B
F,B,A
F,B,A,F
F,B,A,F,B
F,B,A,F,B,G
F,B,A,F,B,G,E
F,B,A,F,B,G,E,F
F,B,A,F,B,G,E,F,E
F,B,A,F,B,G,E,F,E,B
F,B,A,F,B,G,E,F,E,B,A
F,B,A,F,B,G,E,F,E,B,A,D
F,B,A,F,B,G,E,F,E,B,A,D,F
F,B,A,F,B,G,E,F,E,B,A,D,F,E
F,B,A,F,B,G,E,F,E,B,A,D,F,E,E
F,B,A,F,B,G,E,F,E,B,A,D,F,E,E,D
$

我需要的输出:

F,
B,F,
A,B,F,
A,B,F,
A,B,F,
A,B,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
A,B,E,F,
A,B,D,E,
A,B,D,F,
A,D,E,F,
A,D,E,F,
A,D,E,F,

尝试获取输出

 awk -F, ' { split("",arr); for(i=NF;i>0;i--) { if(!$i in arr && length(arr)<4 ) arr[$i]=1 }; for(i in arr) printf("%s,",i); print "" } ' last_cols.txt

我只是得到空行。

由于这将是 运行 在 bash 环境中,我也欢迎其他解决方案。

检查这个

awk -F, '{
    delete arr;
    for(i=NF;i>0;i--) {
        arr[$i]=1
        if (length(arr)==4) {
            break;
        }
    };
    for(i in arr) {
        printf("%s,",i);
    }
    printf("\n");
} ' last_cols.txt

使用这个 Perl 单行代码:

perl -F',' -lane 'my %seen; my @u = grep { !$seen{$_}++ } reverse @F; splice @u, 4; print map { "$_," } sort @u;' last_cols.txt

Perl 单行代码使用这些命令行标志:
-e : 告诉 Perl 查找内联代码,而不是在文件中。
-n :一次循环输入一行,默认分配给 $_
-l : 在执行内联代码之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"),并在打印时附加它。
-a : 在空格或 -F 选项中指定的正则表达式上将 $_ 拆分为数组 @F
-F',' : 在逗号上拆分为 @F,而不是在空格上。

my @u = grep { !$seen{$_}++ } reverse @F; :反转从输入行读取的字符串数组。 Select 唯一元素,保持顺序。
splice @u, 4; : 只保留前 4 个元素。
print map { "$_," } sort @u; : 对结果字符串进行 ASCIIbet 排序,附加逗号并打印。

另请参见:
perldoc perlrun: how to execute the Perl interpreter: command line switches

请您尝试以下操作:

perl -F, -alne '
    for $f (reverse @F) {
        $seen{$f}++;
        last if (keys %seen) >= 4;
    }
    print join(",", sort keys %seen);
    undef %seen;
' last_cols.txt

使用 GNU awk,您能否尝试使用显示的示例进行以下编写和测试。输出将按照 OP 排序。

awk '
BEGIN{
  FS=OFS=","
}
{
  val=""
  delete arr
  delete arr2
  for(i=NF;i>0;i--){
    if(!arr[$i]++){
       val=(val?val OFS:"")$i
    }
    if(length(arr)==4){
       break
    }
  }
  num=split(val,arr2,",")
  asort(arr2)
  for(key in arr2){
    printf("%s,%s",arr2[key],key==length(arr2)?ORS:"")
  }
}' Input_file

输出如下。

F,
B,F,
A,B,F,
A,B,F,
A,B,F,
A,B,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
A,B,E,F,
A,B,D,E,
A,B,D,F,
A,D,E,F,
A,D,E,F,
A,D,E,F,

解释:为以上添加详细解释。

awk '                             ##Starting awk program from here.
BEGIN{                            ##Starting BEGIN section of this program from here.
  FS=OFS=","                      ##Setting field separator and output field separator as comma here.
}
{
  val=""                          ##Nullifying val here.
  delete arr                      ##Deleting arr array here.
  delete arr2                     ##Deleting arr2 array here.
  for(i=NF;i>0;i--){              ##Running for loop from last field to first field each line.
    if(!arr[$i]++){               ##Checking condition if current field is NOT present in arr then do following.
       val=(val?val OFS:"")$i     ##Creating val which has current field value and keep on concatenating in its value.
    }
    if(length(arr)==4){           ##Checking condition if length of arr is 4 then do following.
       break                      ##Using break to come out of the loop.
    }
  }
  num=split(val,arr2,",")         ##Splitting val into arr2 with comma as delimiter.
  asort(arr2)                     ##Using asort to sorting values into arr2.
  for(key in arr2){               ##Going through arr2 here.
    printf("%s,%s",arr2[key],key==length(arr2)?ORS:"")   ##Printing values of arr2 one by one and printing new line when its last value of arr2.
  }
}
'  Input_file                     ##Mentioning Input_file name here.

这是在 gnu awk 中获得此输出的一种方法:

awk -F, 'BEGIN {PROCINFO["sorted_in"]="@ind_str_asc"} {delete a; for (i=NF; length(a)<4 && i>0; --i) a[$i]; [=10=]=""; for (i in a) [=10=] = [=10=] i FS} 1' file

F,
B,F,
A,B,F,
A,B,F,
A,B,F,
A,B,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
A,B,E,F,
A,B,D,E,
A,B,D,F,
A,D,E,F,
A,D,E,F,
A,D,E,F,

为了使其更具可读性:

awk -F, 'BEGIN {
   PROCINFO["sorted_in"] = "@ind_str_asc"   # to sort by key ascending order
}
{
   delete a                                 # delete array a
   for (i=NF; length(a)<4 && i>0; --i)      # loop from last column backwards
      a[$i]                                 # store in array a and keep it sorted
   [=11=] = ""                                  # reset [=11=] to ""
   for (i in a)                             # loop through array a
      [=11=] = [=11=] i FS                          # append j and FS to [=11=]
} 1                                         # print each record
' file

我可以通过在密钥检查中添加括号来获得结果。 !$i in arr!($i in arr)

awk -F, ' { 
split("",arr); 
for(i=NF;i>0;i--) { 
  if(!($i in arr) && length(arr)<4 ) arr[$i]=1 }; 
  for(i in arr) printf("%s,",i); print "" 
} ' last_cols.txt


F,
B,F,
A,B,F,
A,B,F,
A,B,F,
A,B,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
B,E,F,G,
A,B,E,F,
A,B,D,E,
A,B,D,F,
A,D,E,F,
A,D,E,F,
A,D,E,F,