How can I generate from this INPUT in "general"

INPUT (/proc/net/ip_conntrack)

udp      17 0 src= dst= sport=29249 dport=39802 packets=3 bytes=408 [UNREPLIED] src= dst= sport=39802 dport=29249 packets=0 bytes=0 mark=0 use=2
udp      17 146 src= dst= sport=56932 dport=43645 packets=924 bytes=406167 src= dst= sport=43645 dport=56932 packets=1042 bytes=546092 [ASSURED] mark=0 use=2
tcp      6 118 SYN_SENT src= dst= sport=2518 dport=47385 packets=2 bytes=104 [UNREPLIED] src= dst= sport=47385 dport=2518 packets=0 bytes=0 mark=0 use=2
udp      17 147 src= dst= sport=56937 dport=43647 packets=924 bytes=406167 src= dst= sport=43647 dport=56937 packets=1042 bytes=546092 [ASSURED] mark=0 use=2
tcp      6 119 SYN_SENT src= dst= sport=2514 dport=47384 packets=2 bytes=104 [UNREPLIED] src= dst= sport=47384 dport=2514 packets=0 bytes=0 mark=0 use=2
udp      17 163 src= dst= sport=67 dport=68 packets=29 bytes=9512 src= dst= sport=68 dport=67 packets=27 bytes=8856 [ASSURED] mark=0 use=2
tcp      6 1 TIME_WAIT src= dst= sport=55479 dport=80 packets=7 bytes=725 src= dst= sport=80 dport=55479 packets=5 bytes=1963 [ASSURED] mark=0 use=2

to this output?


udp   3
tcp   2
udp   1
tcp   1

So that from the INPUT datas the OUTPUT would be 3 columns:

protocoll   src-ip-address  count-connection-numbers

So that the IP with the most number of connections would be at top.

5 Answers 5


Using sed, uniq, sort, awk and column:

sed -n -r 's/^(udp|tcp)\s*[^=]*=([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*$/\1 \2/p' infile \
  | sort | uniq -c | sort -nr | awk '{print $2" "$3" "$1'} | column -t > outfile

You can use perl one-liner to get it done, it's very easy!

perl -lane 'print "$F[0] $1" if /src=(.*?)\s/' /proc/net/ip_conntrack | sort | uniq -c | sort -rn -k 1

There are two steps: extract the protocol and source addresses, and collect and sort. You already know how to do the second, so let's see how to do the first.

You already had a way to extract the source addresses:

sed -ne 's/^.*src=\([^ ]*\).*/\1/p'

That extracts the last src= field though; here we want to extract the first. It's a bit inconvenient in sed, but can be done.

sed -n -e 's/\(src=[^ ]*\).*/\1/' -e 's/^.*src=\([^ ]*\).*/\1/p'

To retain the first field, just apply the last replacement to the part after the first space.

sed -n -e 's/\(src=[^ ]*\).*/\1/' -e 's/ .*src=\([^ ]*\).*/ \1/p'

This is terse and not very clear. Here's an about equally terse, but clearer way to get the same output with awk. Call match to find the extent of the first src= field, then print out the corresponding part of the line.

awk 'match($0, / src=[^ ]*/) {print $1 substr($0, RSTART, RLENGTH)}'

Finally, pipe into the second stage (sort, obtain counts, and sort by count).

awk 'match($0, / src=[^ ]*/) {print $1 substr($0, RSTART, RLENGTH)}' |
sort | uniq -c | sort -nr
  • s/ .*src= makes a greedy grab and returns the 2nd src= ip.. One alternative is 's/ [^=]*=
    – Peter.O
    Jun 23, 2011 at 19:20
  • @fred I shouldn't post so late at night, I hadn't even noticed the second src= field. s/ [^=]*=\([^ ]*\)/\1/p would work, but it would rely on src= being the first field with an equal sign, and that feels too inflexible. (P.S. I forget, do you do Perl? You may be interested in this text replacement benchmark.) Jun 23, 2011 at 20:22
  • I too hadn't noticed the second src= until after I had +1'd your answer, based on a visual 'test', and then thought I'd better give it a 'real' test... Re. perl: I look on in awe :)
    – Peter.O
    Jun 23, 2011 at 22:25

Using awk and sort:

/usr/bin/awk -F" " '
  proto = $1
  for(i = 2; i <= NF; ++i) 
    if ($i ~ /^src=/) 
      scrip = $i
      srcip = sub(/^src=/, "", scrip)
      key = proto SUBSEP scrip
  for (var in a)
    split(var, subkey, SUBSEP)
    printf "%-5s %-18s %-8s\n", subkey[1], subkey[2], a[var]
' infile | sort -rn -k3,3
  • Your output prints both instances (per line) of src=... The sample output requires only the first instance...
    – Peter.O
    Jun 23, 2011 at 19:42
use strict;
use warnings;

my %count;

# extract protocol and source-ip-address, count rows with same values
while(<>) {
  if (/^([^ ]+).*src=([0-9.]+)/) {
    $count{"$1 $2"}++;

# sort by count
for my $p_src (sort {$count{$b} <=> $count{$a}} keys %count) {
  print "$p_src\t$count{$p_src}\n";

Example (your data isn't very interesting)

$ eg.pl eg.txt
tcp        1
tcp       1
tcp       1
udp       1
udp      1
udp 1
udp 1
  • Based on the sample output provided, only the first instance (per line) of src= ip should be printed...
    – Peter.O
    Jun 23, 2011 at 19:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .