{"id":32,"date":"2013-09-17T22:00:38","date_gmt":"2013-09-17T20:00:38","guid":{"rendered":"http:\/\/www.anginf.de\/?p=32"},"modified":"2014-07-10T17:14:17","modified_gmt":"2014-07-10T15:14:17","slug":"sortierung-von-mysql-ist-anders-als-die-sortierung-von-bash","status":"publish","type":"post","link":"https:\/\/www.anginf.de\/?p=32","title":{"rendered":"Sortierung von mysql ist anders als die Sortierung von bash"},"content":{"rendered":"<p>Um schnell pr\u00fcfen zu k\u00f6nnen, ob ein Element in einer Datenbank-Tabelle enthalten ist, ohne daf\u00fcr jedesmal die Datenbank abzufragen, wollte ich diese eine Tabelle, deren Inhalt ich pr\u00fcfen wollte, in einem bash-Array ablegen.<\/p>\n<p>Die Datenbank-Tabelle hat folgenden Inhalt (neben der ID):<\/p>\n<pre>AR\r\n\u00c4R\r\nZZ\r\nX\u00c9\r\nX\u00c9 F\r\nXE, J\r\nX\u00c9; P\r\nX\u00c9; S<\/pre>\n<p>\u00dcbernehmen kann man den Inhalt der mysql-Tabelle in einem bash-Script eigentlich ganz leicht:<\/p>\n<pre lang=\"bash\">while read line\r\ndo\r\n  tablearray+=(\"${line}\")\r\ndone <<(${mysqlcmd} -Bse \"select name from table order by name\")<\/pre>\n<p>Um nun auch <strong>schnell<\/strong> pr\u00fcfen zu k\u00f6nnen, ob ein Element bereits in dem Array enthalten ist, wollte ich ungern alle Elemente durchlaufen. Stattdessen lasse ich bereits mysql die Daten sortieren. Im bash-Script selbst \"suche\" ich dann \u00fcber einen Bin\u00e4ren-Suchbaum-Ansatz innerhalb des Bash-Arrays:<\/p>\n<pre lang=\"bash\">function contains()\r\n{\r\n  declare -a haystack=(\"${!2}\")\r\n  local needle=${1}\r\n  local low=0\r\n  local lowold=0\r\n  local high=${#haystack[@]}\r\n  local highold=${#haystack[@]}\r\n  let \"pos = high \/ 2\"\r\n  while true\r\n  do\r\n    if [[ \"${haystack[${pos}]}\" == \"${needle}\" ]]; then\r\n      # Found\r\n      return 0\r\n    fi\r\n    if [ \"${haystack[${pos}]}\" \\> \"${needle}\" ]; then\r\n      let \"high = pos\"\r\n      let \"pos = low + ( high - low ) \/ 2\"\r\n    else\r\n      let \"low = pos\"\r\n      let \"pos = low + ( high - low ) \/ 2\"\r\n    fi\r\n    if [ ${highold} -eq ${high} ]; then\r\n      if [ ${lowold} -eq ${low} ]; then\r\n        # Not found\r\n        return 1\r\n      fi\r\n    fi\r\n    let \"lowold = low\"\r\n    let \"highold = high\"\r\n  done\r\n}<\/pre>\n<p>Aufrufen kann man diese Funktion bequem innerhalb des Scripts mit:<\/p>\n<pre lang=\"bash\">  if contains \"SearchString\" tablearray[@] ; then<\/pre>\n<p>Nebeneffekt hierbei ist allerdings, dass lokal eine Kopie des Arrays angelegt wird. Wer das nicht m\u00f6chte, muss den Teil <code>declare -a haystack=(\"${!2}\")<\/code> auslassen und statt <code>$haystack<\/code> immer auf den Original-Array verweisen. Das f\u00fchrt auch leider dazu, dass man f\u00fcr jedes Array eine eigene Funktion braucht...<\/p>\n<p>Bei einigen Suchen konnte das Element nicht gefunden werden (obwohl es im Array enthalten war) und - noch schlimmer - das contains() lief in einer Endlos-Schleife weiter. Nach kurzer Analyse war klar, dass die Sortierung von bash eine andere ist als das, was mysql verwendet.<\/p>\n<p>Ich hatte schon vermutet, dass es wahrscheinlich an den CHARSET oder COLLATE bzw. COLLATION von mysql liegt, und habe mir daher ein bash-Script geschrieben, welches pr\u00fcft, welche Kombinationen genauso sortieren wie bash. Wer Interesse hat, kann sich das Script gerne herunterladen: <a href=\"download\/scripts\/mysql_collate.sh\">mysql_collate.sh<\/a><\/p>\n<p>Das Skript \u00fcberpr\u00fcft dabei zwei Dinge gleichzeitig:<\/p>\n<ol>\n<li>Sind die Sonderzeichen korrekt in die Datenbank eingespeichert worden und k\u00f6nnen auch korrekt wieder ausgelesen werden?<\/li>\n<li>Ist die Sortierung von bash mit der mysql-\"ORDER BY\" Klausel kompatibel?<\/li>\n<\/ol>\n<p>Auf meinem System:<\/p>\n<pre lang=\"bash\">$ mysql --version\r\nmysql  Ver 14.14 Distrib 5.5.32, for debian-linux-gnu (x86_64) using readline 6.2<\/pre>\n<p>Erhalte ich folgende g\u00fcltige Kombinationen:<\/p>\n<pre>dec8 \/ dec8_bin\r\ncp850 \/ cp850_bin\r\nhp8 \/ hp8_english_ci\r\nhp8 \/ hp8_bin\r\nlatin1 \/ latin1_bin\r\nlatin2 \/ latin2_bin\r\nujis \/ ujis_japanese_ci\r\nujis \/ ujis_bin\r\ncp1250 \/ cp1250_bin\r\nlatin5 \/ latin5_bin\r\nutf8 \/ utf8_bin\r\nutf8 \/ utf8_icelandic_ci\r\nucs2 \/ ucs2_bin\r\nucs2 \/ ucs2_icelandic_ci\r\nkeybcs2 \/ keybcs2_bin\r\nmacce \/ macce_bin\r\nmacroman \/ macroman_bin\r\ncp852 \/ cp852_bin\r\nlatin7 \/ latin7_bin\r\nutf8mb4 \/ utf8mb4_icelandic_ci\r\nutf16 \/ utf16_icelandic_ci\r\ncp1257 \/ cp1257_bin\r\nutf32 \/ utf32_bin\r\nutf32 \/ utf32_icelandic_ci\r\neucjpms \/ eucjpms_japanese_ci\r\neucjpms \/ eucjpms_bin<\/pre>\n<p>Ein wenig unangenehm ist mir das schon, aber ich arbeite nun mit einem bin\u00e4ren Ansatz und habe f\u00fcr meine Zwecke <code>latin1 \/ latin1_bin<\/code> ausgew\u00e4hlt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Um schnell pr\u00fcfen zu k\u00f6nnen, ob ein Element in einer Datenbank-Tabelle enthalten ist, ohne daf\u00fcr jedesmal die Datenbank abzufragen, wollte ich diese eine Tabelle, deren Inhalt ich pr\u00fcfen wollte, in einem bash-Array ablegen. Die Datenbank-Tabelle hat folgenden Inhalt (neben der ID): AR \u00c4R ZZ X\u00c9 X\u00c9 F XE, J X\u00c9; P X\u00c9; S \u00dcbernehmen kann &hellip; <a href=\"https:\/\/www.anginf.de\/?p=32\" class=\"more-link\"><span class=\"screen-reader-text\">Sortierung von mysql ist anders als die Sortierung von bash<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"_links":{"self":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/32","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=32"}],"version-history":[{"count":10,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/32\/revisions"}],"predecessor-version":[{"id":121,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/32\/revisions\/121"}],"wp:attachment":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}