ubuntuusers.de

Auslesen Datenbankwerte in Array

Status: Ungelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

halloICKEbins

Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Morgen Leute,

nach 2 Tagen rumprobieren und Forum lesen gebe ich auf.

Ich würde gerne aus einer Datenbank Werte auslesen und sie in Array schreiben lassen um sie später für eine Suchroutine weiterbenutzen zu können.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash

mysql -D datenbankname -u username -ppasswort -e "SELECT name FROM user" | while read line; 

do
        NULL[]=$(echo "SELECT name FROM user where name='$line'" | mysql -D datenbankname -u username -ppasswort)
done

echo $NULL[1]
#bzw. alle Werte hintereinander ausgeben


Ausgabe:

/bin/blabla.sh: 19: /bin/blabla.sh: NULL[]=name: not found
[1]

Warum geht es nicht ??? Geht es auch mit mehreren Spalten, um diese gleich in ein ARRAY zu überführen ???

Bearbeitet von rklm:

Syntax

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

So geht man nicht mit Arrays um:

1
2
NULL[]=7
bash: NULL[]: Falscher Feldbezeichner.

Abgesehen davon, dass NULL ein denkbar schlechter Bezeichnername ist. Bei der Zuweisung eines ganzen Arrays steht links der Name ohne alles:

1
2
3
4
5
6
7
NULL=($(echo "SELECT name FROM user where name='$line'"))
echo $NULL
# SELECT
echo ${NULL[@]}
# SELECT name FROM user where name=''
echo ${NULL[3]}
# user

Rechts vom Zuweisungsoperator = steht ein runder Klammernausdruck

1
2
3
zahlen=(1 2 3 4)
echo ${zahlen[3]}
# 4

Darin kann ein Befehl stehen, dessen Ausgabe mit $(...) zum Inhalt des Arrays wird:

1
2
3
dateien=($(ls)) 
echo ${dateien[3]}
# EA130.svg

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

@halloICKEbins Das Skript hat gleich mehrere Probleme.

Wegen der Pipe wird das while in einer Untershell ausgeführt, dass heisst alles was bis zum done mit Variablen gemacht wird ist nach dem done nicht sichtbar, denn das ist dann wieder in der Elternshell.

Was Du da in der Schleife versuchst ist keine gültige Shell-Syntax:

bj@god:~$ NULL[]=42
bash: NULL[]: bad array subscript 

Wie bist Du auf diese Idee gekommen? Das sieht so ein bisschen nach raten und versuchen ob man in Bash auch PHP-Syntax verwenden kann aus.

Die Abfrage macht nicht viel Sinn. Bei SELECT name FROM user where name='$line' kommt ja immer nur wieder der Name heraus, denn man schon in $line hatte. Ausser wenn man in $line etwas hat was nicht in der Datenbank enthalten ist. Aber $line kommt hier ja durch eine Datenbankabfrage aller Namen zustande, also ist die Chance recht klein, dass der Name dann nicht in der Datenbank enthalten ist.

Allerdings wird $line ziemlich wahrscheinlich nicht (nur) die Namen enthalten, denn die erste Zeile dürfte der Spaltenname sein. Also in diesem Fall name.

Nach der Schleife ist dann wieder etwas was keine (sinnvolle) Shell-Syntax ist:

bj@god:~$ echo $NULL[1]
[1] 

Um auf Indexwerte zuzugreifen muss man geschweifte Klammern setzen:

bj@god:~$ echo ${NULL[1]}

bj@god:~$ NULL=(1 2 3)
bj@god:~$ echo ${NULL[1]}
2 

Die Ausgabe eines Programms kann man beispielsweise mit der „compound assignment“-Syntax als Array zuweisen. Allerdings muss man da mit Leerzeichen aufpassen und $IFS entsprechend ändern wenn nur an Zeilenenden aufgeteilt werden soll.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/bin/bash
OLD_IFS=$IFS
IFS=$'\n'
names=($(mysql -D 'datenbankname' -u 'username' -p'password' -e 'SELECT name FROM user'))
IFS=$OLD_IFS

unset 'names[0]'  # Remove column header.

for name in "${names[@]}"; do
    echo "$name"
done

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Danke schon mal für die umfangreichen Antworten...

Bei Ausführung des Scriptes kommt die Fehlermeldung:

/bin/blabla.sh: 21: unset: names[0]: bad variable name


Kann ich auch ohne großen Aufwand mehrere Werte (mehrere Spalten abfragen) speichern ...

SELECT vorname, nachname FROM user

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

@halloICKEbins Also bei mir nicht. Und das steht ja auch nicht in Zeile 21 sondern in Zeile 7. Wenn man Fehlermeldungen zeigt, dann sollte man auch den dazugehörigen Quelltext zeigen, sonst können wir ja nur raten wie das zustande gekommen ist.


Ohne grossen Aufwand ist bei Shell-Skripten so eine Sache. Wenn man kompliziertere Datenstrukturen braucht, und da gehören IMHO aus Bash-Sicht mehrdimensionale/zweidimensionale Arrays bereits dazu, dann würde ich das nicht mehr versuchen mit der Bash zu lösen, sondern eine ”richtige” Programmiersprache verwenden.

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Sorry...

Also bei "reinem" Script kommt die gleiche Fehlermeldung in Zeile 7. Kommentiere ich Zeile 7 aus kommt ...

/bin/blabla.sh: 9: /bin/blabla.sh: Bad substitution

misterunknown Team-Icon

Ehemalige
Avatar von misterunknown

Anmeldungsdatum:
28. Oktober 2009

Beiträge: 4403

Wohnort: Sachsen

Also ich würde dir für diesen Anwendungsfall generell von einem Shell-Skript abraten. Für solche Sachen wurden Skript-Sprachen wie Perl, PHP oder Python geschaffen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

Wie startest Du /bin/blabla.sh?

Und überhaupt ist /bin nicht der Ort, unfertige Skripte abzulegen.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

Mal als Beispiel wie die Abfrage und Ausgabe von Vor- und Nachname mit CoffeeScript aussehen könnte.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env coffee
'use strict'
mysql = require 'mysql2/promise'


main = ->
  mysql.createConnection
      host: 'localhost'
      user: 'username'
      password: 'password'
      database: 'database'
    
    .then (connection) ->
      connection.execute 'SELECT name, vorname FROM user'
        .then ([rows, fields]) ->
          for row in rows
            console.log "name: #{row.name}, vorname: #{row.vorname}"
          connection.end()
        .catch (error) ->
          console.log error
          connection.end()
    .catch console.log


main() if require.main == module

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Das ist richtig...

Mein Problem ist, dass ich MYSQL als Schnittstelle zwischen dem Nutzer auf PHP-Basis zu einem Linix-System benötige, da der Nutzer keine Rechte an dem System bekommen soll und auch das System nicht erreicht. Mit Hilfe der von Linux gezogenen Information aus MYSQL fragt das System wiederrum Logdateien ab, welche dann gespeichert werden soll. Diese werden dann mittels Cronjob auf den PHP-Server gezogen.

Anders geht es nicht wegen der Sicherheitsarchitektur...wollte nach Möglichkeit nicht zu einer Programmiersprache wechseln

Aber wenn ihr denkt es ist sinnvoller, welche würdet ihr empfehlen ???

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13209

halloICKEbins schrieb:

Mein Problem ist, dass ich MYSQL als Schnittstelle zwischen dem Nutzer auf PHP-Basis zu einem Linix-System benötige, da der Nutzer keine Rechte an dem System bekommen soll und auch das System nicht erreicht. Mit Hilfe der von Linux gezogenen Information aus MYSQL fragt das System wiederrum Logdateien ab, welche dann gespeichert werden soll. Diese werden dann mittels Cronjob auf den PHP-Server gezogen.

Ich verstehe nur Bahnhof.

Anders geht es nicht wegen der Sicherheitsarchitektur...wollte nach Möglichkeit nicht zu einer Programmiersprache wechseln

Was ist denn PHP, wenn nicht eine Programmiersprache?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

@halloICKEbins Gerade wenn es um Sicherheit geht und im Zusammenhang mit dynamisch erstellten SQL-Abfragen würde ich kein Shell-Skript schreiben. Bei dem was Du gezeigt hast wird ja mindestens der Benutzername irgendwann einmal in eine SQL-Abfrage hinein formatiert — wenn die Benutzer ihre Namen wählen können, hast Du damit vielleicht auch schon ein Einfallstor für eine SQL-Injection.

Frag nie nach einer Programmiersprache wenn Du möglichst eine vorgeschlagen bekommen möchtest. ☺ Es gibt viele und jeder hat da so seine Vorlieben und Abneigungen. CoffeeScript, Perl, PHP, und Python[1] wurden ja schon genannt. Mindestens JavaScript und Ruby könnte man noch nennen.

  • 1: Aufzählung der Sprachen in alphabetischer Reihenfolge.

misterunknown Team-Icon

Ehemalige
Avatar von misterunknown

Anmeldungsdatum:
28. Oktober 2009

Beiträge: 4403

Wohnort: Sachsen

halloICKEbins schrieb:

Aber wenn ihr denkt es ist sinnvoller, welche würdet ihr empfehlen ???

Nimm einfach eine Sprache die du ausreichend kennst. Wenn du schon mit PHP gearbeitet hast, dann nimm das (auch damit kann man CLI-Tools bauen), ansondern würde wie gesagt auch Perl oder Python oder Ruby oder irgendeine andere Skriptsprache funktionieren.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4687

Wohnort: Berlin

Spasseshalber mal ein Beispiel in Ruby das auch eine Abfrage zeigt wo ein Wert in eine Abfrage eingesetzt wird ohne das man sich eine SQL-Injection einhandelt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env ruby
require 'dbi'


def main
    connection = DBI.connect 'dbi:Mysql:datenbank:localhost', 'user', 'password'
    connection.select_all 'SELECT name FROM user' do |row|
        puts "Name: #{row['name']}"
    end

    name = 'Meier'
    row = connection.select_one 'SELECT vorname FROM user WHERE name=?', name
    puts "Der Vorname von #{name} lautet #{row['vorname']}."

    connection.commit
rescue DBI::DatabaseError => error
    puts "Error code:    #{error.err}"
    puts "Error message: #{error.errstr}"
    connection.rollback
ensure
    connection.disconnect if connection
end


main if __FILE__ == $PROGRAM_NAME
Antworten |