开发者

Counting and matching process

开发者 https://www.devze.com 2023-03-27 04:03 出处:网络
I have a matching problem with awk :( I will count first column elements in main.file and if its value is more than 2 I will print the first and the second column.

I have a matching problem with awk :(

I will count first column elements in main.file and if its value is more than 2 I will print the first and the second column.

main.file

1725009 7211378
3353866 11601802
3353866 8719104
724973 3353866
3353866 7211378

For example number of "3353866" in the first column is 3, so output.file will 开发者_开发知识库be like that:

output.file

3353866 11601802
3353866 8719104
3353866 7211378

How can I do this in awk?


If you mean items with at least 3 occurrences, you can collect occurrences in one array and the collected values as a preformatted or delimited string in another.

awk '{o[$1]++;v[$1]=v[$1] "\n" $0}
    END{for(k in o){if(o[k]<3)continue;
        print(substr(v[k],1)}' main.file

Untested, not at my computer. The output order will be essentially random; you'll need another variable to keep track of line numbers if you require the order to be stable.

This would be somewhat less hackish in Perl or Python, where a hash/dict can contain a structured value, such as a list.


Another approach is to run through the file twice: it's a little bit slower, but the code is very neat:

awk '
  NR==FNR {count[$1]++; next}
  count[$1] > 2 {print}
' main.file main.file


awk '{store[$1"-"lines[$1]] = $0; lines[$1]++;}
  END {for (l in store) {
    split(l, pair, "-"); if (lines[pair[1]] > 2) { print store[l] } } }'


One approach is to track all the records seen, the corresponding key $1 for each record, and how often each key occurs. Once you've record those for all the lines, you can then iterate through all the records stored, only printing those for which the count of the key is greater than two.

awk '{ 
    record[NR] = $0; 
    key[$0] = $1; 
    count[$1]++ 
} 

END { 
    for (n=1; n <= length(record); n++) { 
        if (count[key[record[n]]] > 2) { 
            print record[n] 
        }
    } 
}'


Sort first, and then use awk to print only when you have 3 times or more the 1st field:

cat your_file | sort -n | awk 'prev == $1 {count++; p0=p1; p1=p2; p2=$2}
prev != $1 {prev=$1; count=1; p2=$2}
count == 3 {print $1 " " p0; print $1 " " p1; print $1 " " p2}
count > 3 {print $1 " " $2}'

This will avoid awk to use too much memory in case of big input file.


based on how the question looks and the Ray Toal edit, I'm guessing you mean based on count, so something like this works:

awk '!y[$1] {y[$1] = 1} x[$1] {if(y[$1]==1) {y[$1]==2; print $1, x[$1]}; print} {x[$1] = $2}'
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号