f.zz.de
posts /

Sorting interface names

Posted Wed 13 Jan 2016 10:32:08 AM CET Florian Lohoff
in

Immer derselbe Ärger. Sortieren von Interface Namen in Webfrontends. Am Ende kriegt man sowas und soll die schön sortieren.

FastEthernet1
Port-channel5
TenGigabitEthernet1/1/1
Port-channel10
eth0.5
TenGigabitEthernet1/1/1.3
eth0.5:3
FastEthernet1.1
TenGigabitEthernet2/2/32
eth0
Port-channel5.4055
ae0.3

Was sich erstmal als nicht so schlimm darstellt aber dann doch beliebig doof wird. Wenn man einfach die handelsüblichen String Sortierroutinen in Perl, Javascript oder einer anderen Sprache nimmt wird Lexikografisch sortiert. Das geht natürlich beliebig schief. So werden dann die Port-channel falschrum sortiert:

Port-channel10
Port-channel5

was natürlich Lexikographisch absolut richtig ist aber leider nicht was was man haben möchte.

Also muss man den String an "word" Boundaries zerlegen wobei hier sowohl der Übergang von Buchstabe auf Zahl wie Sonderzeichen und auch umgekehrt gilt.

Wir klassifizieren die Zeichen:

  function chartype(ch) {
    if (ch >= 'a' && ch <= 'z') {
      return 1;
    }

    if (ch >= 'A' && ch <= 'Z') {
      return 1;
    }

    if (ch >= '0' && ch <= '9') {
      return 2;
    }

    switch(ch) {
      case('-'):
      case('/'):
      case(':'):
      case('.'):
        return 3;
    }

    return 0;
  }

Danach zerlegen wir den String in ein array:

if (chartype(ch) != chartype(last)) {
  elements.push(str.substr(0, i));
  str=str.slice(i,str.length);
}

Danach sind die interfaces schön zerlegt:

["TenGigabitEthernet", "2", "/", "1", "/", "31"]

Und können danach ganz einfach das Array rekursiv vergleichen als function für array.sort(). Hier wird wenn es numerische Elemente sind numerisch verglichen andernfalls wird localeCompare bemüht. Sollten die elemente gleich sein wird die nächste Ebene bemüht.

  function shortlist_sort_deeparray(a, b, i) {
    /* Elements numeric ? */
    if (!isNaN(a[i]) && !isNaN(b[i])) {
      rc=a[i]-b[i];
    } else {
      rc=a[i].localeCompare(b[i]);
    }

    if (rc == 0) {
      return shortlist_sort_deeparray(a, b, i+1);
    }
    return rc;
  }

Es gibt noch ein bischen Optimierungspotential. So könnte man den chartype 3 also die "Sonderzeichen" einfach nicht in das Array packen. Was natürlich dann bei eth0:3 und eth0.3 zu undefiniertem Verhalten führt. Da es normalerweise um <100 Interfaces geht macht das ganze auch wenig Sinn.

[[!img Error: "media/201601131032.sorting_interface_names.jpg" does not seem to be a valid jpeg file]]