试图从动态 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,
我需要从文件中的每条记录中获取最后 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,