|
matze31
Anmeldungsdatum: 25. Oktober 2015
Beiträge: 836
|
Hallo, gibt es eine Möglichkeit, in bash so eine Art dictonary zu deklarieren und diese dann in eine Datei zu schreiben. Um später dann wieder drauf zugreifen zu können und den x-ten Wert zu ändern? Beispiel: Ich habe name1=aaa, name2=bbb, name3=ccc u.s.w. Jetzt möchte ich aber den Wert name2 ändern von bbb auf ddd. Die Datei muss auch für anderen Scripte erreichbar sein. Wie kann man so etwas realisieren?
|
|
verdooft
Anmeldungsdatum: 15. September 2012
Beiträge: 4578
|
Wenn was externes klar geht, ist in den Quellen: crudini - edit ini files from the command line shell http://www.pixelbeat.org/programs/crudini/
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17672
Wohnort: Berlin
|
Ja, und ja. a) Wenn Du selbst Buch führst, kannst Du schreiben: (Dictionary als File anlegen) | echo "a=foo
b=7
c=/dev/cdrom" > conf.sh
|
Die Werte einlesen: | source conf.sh
# Einen Wert ändern:
b=8
# geänderte Werte in Datei schreiben
echo "a=$a
b=$b
c=\"$c\""
|
Das source conf.sh können auch andere Files benutzen. Problem: Raceconditions. Wenn Script 1 den Wert schreibt weiß Script 2 nichts davon, außer über umständliche Mechanismen erreichbar. Andere Scripte sehen die neuen Werte erst, wenn sie erneut conf.sh einlesen. Bei vielen Variablen wird es wahrscheinlich unübersichtlich. Lesen andere Scripte die Werte ein, so muss man auch aufpassen, dass es nicht zu Namenskollisionen kommt, also Script 3 benutzt vielleicht die Variable "tmp" und Script 1 führt später auch ein *tmp* ein. b) Um nicht alle Variablen einzeln beim Speichern aufführen zu müssen kann man ein assoziatives Array verwenden.
| declare -A dict
dict[a]=foo
dict[b]=7
dict[c]="/dev/cdrom"
|
Die anderen Probleme (Namenskollision, Raceconditions) löst das natürlich nicht, aber der Code bleibt auch bei vielen Variablen knapp.
Das Einlesen wird auch komplizierter als einfach source aufzurufen. Siehe auch help source.
|
|
TK87
Anmeldungsdatum: 8. Juli 2019
Beiträge: 303
Wohnort: Aachen
|
Moin, also Werte nach bestimmten Mustern in eine Datei schreiben und abrufen? - Da schreit für mich alles schon gerade zu nach einer JSON-Datei. In Bash lässt sich diese ganz leicht mit jq erstellen und Bearbeiten. Zudem lässt sich das Format aber auch in anderen Sprachen easy verwalten. Gruß Thomas
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13365
|
matze31 schrieb:
Ich habe name1=aaa, name2=bbb, name3=ccc u.s.w. Jetzt möchte ich aber den Wert name2 ändern von bbb auf ddd.
Meinst Du ein Array oder ein Dictionary? Letzteres hat typischerweise beliebige Schlüssel, während ein Array mit positiven Ganzzahlen (die starten meist bei 0) indiziert wird.
Die Datei muss auch für anderen Scripte erreichbar sein.
Meinst Du damit den physischen Zugriff des Lesens oder soll "erreichbar" auch bedeuten, dass die Datei ein Format hat, das womöglich von verschiedenen Skripten in verschiedenen Sprachen lesbar ist. Dann böte sich etwas wie Yaml oder JSON an. Man könnte auch Zeilen als Werte nehmen, also Newline als Trennzeichen. Wenn man das rein in bash machen will, dann geht z.B. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #!code bash
dict_file=~/.dict
dict_lese(){
dict=()
while read -r v; do
dict+=("$v")
done <"$dict_file"
}
dict_schreibe(){
for v in "${dict[@]}"; do
echo "$v"
done >|"$dict_file"
}
|
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17672
Wohnort: Berlin
|
Wieso JSON? Ich sehe Json als geeignetes Format um Konstrukte, wie sie für objektorientierte Sprachen typisch sind, an:
| struct Mitarbeiter {
int: id
String: name
}
struct Abteilung {
int: id
String: name
Mitarbeiter[]: mitarbeiter
}
|
, wo man Verästelungen hat. Wo ist der Vorteil gegenüber source, welches ein Buildin ist, so dass man sich keine unnötigen Abhängigkeiten ins Projekt zieht, und welches beim Lesen (vielleicht ist Schreiben für wenige/keine geplanten Anwendungen nötig?) trivial ist: Alle Variablen auf einen Rutsch, ein Einzeiler, eine bekannte Syntax für alle, die ohnehin Bash (oder ein ähnlicher Shelldialekt) lesen?
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1466
|
Da der TS sich etwas unklar ausgedrückt und Begriffe verwendet hat (z.B. dictionary), die eine definierte Bedeutung haben, ist es schwer zu erahnen, was er wirklich will. Aus seinem Beispiel könnte man vermuten, das er eine Liste von Bash-Variablen mit deren Werten für mehrere Scripte zur Verfügung z.B. als Resource-Datei stellen will. Wenn diese meine Vermutung zutrifft, lässt sich das mit einer einfachen sequentiellen Datei realisieren, die das Script zu Beginn mit "source" einliest (siehe Beispiel von user_unknown). Das Ändern der Werte geht über das komplette Neuschreiben der Datei (siehe user_unknown oder rklm als Array). Wenn man nur einzelne Werte ändern will geht dies auch z.B. mittels "sed". Beispiel:
# Erstelle Beispiel-Resource-Datei
RC=conf.sh;name1=aaa;name2=bbb;name3=ccc
# Sichere die Variablen name* in Datei $RC
set | grep ^name >$RC
# ---- nun fängt das Beispiel an
# definiere bash-Funktion zum Setzen/Ändern der Variable $1 auf den Wert $2
function mySet () { eval $1="$2"; grep ^$1= $RC &>/dev/null && sed -i "s/^$1=.*$/$1=${!1}/" $RC || set | grep ^$1= >>$RC ; }
# Ändere die Variable "name2" und füge Array "array4" hinzu
mySet name2 ddd
mySet array4 '( "eins" "zwei" )'
# Prüfe Ergebnis
set | grep -E "^(name|array).*="
cat $RC
Erläuterung der Funktion "mySet". Die Funktion erhält den Bash-Variablen-Namen ($1) und dessen Wert ($2). In der Funktion wird der Wert der Variablen zugewiesen. Wenn die Variable bereits in der Resource-Datei ($RC) definiert ist, wird die neue Zuweisung per "sed" in $RC aktualisiert, sonst per "set|grep)" an $RC angehängt. Variablen, die in $RC auftauchen sollen, sind daher über die Funktion "mySet VariablenName VariablenWert" zu setzen/pflegen. Natürlich kann man statt einer einfachen Datei dies auch in einer .json mit ein paar kleinen Änderungen im "sed" oder "jq" abspeichern.
JS=conf.json
echo "[" >$JS
sed 's/"/\\"/g;s/\([^=]*\)=\(.*\)/{"\1": "\2"},/' $RC >>$JS
sed -zi 's/,\n$/\n]\n/' $JS
cat $JS | jq "."
|
|
TK87
Anmeldungsdatum: 8. Juli 2019
Beiträge: 303
Wohnort: Aachen
|
user_unknown schrieb: Wieso JSON? Ich sehe Json als geeignetes Format um Konstrukte, wie sie für objektorientierte Sprachen typisch sind, an
Das ist so nicht richtig (und dein Beispiel ist auch kein Json). Json ist schlichtweg ein sehr leicht lesbares Format um Mehrdimensionale Tabellen und Listen darzustellen. Also eine Tabelle oder Liste, bei der jeder Zellwert/Listenpunkt wieder eine weitere Tabelle oder Liste sein kann (bis ins unendliche skalierbar).
Wo ist der Vorteil gegenüber source, welches ein Buildin ist
Wo soll ich da bloß anfangen? Neben bereits erwähnten... Einfach nur Wörter in einem Wörterbuch zu deklarieren ist eine Sache - mit Json kannst du zu jedem Wort noch Beschreibungen hinzufügen, diese Kategorisieren, Alternativen hinzufügen, oder was auch immer einem gerade vorschwebt. Das Format ist so leicht lesbar, dass es auch mit jedem gewöhnlichen Textprogramm editierbar ist JQ bringt alles nötige mit, um Werte schnell einfach und sicher nach beliebigen Kriterien filtern oder ändern zu können Das Format lässt sich jederzeit komplett umstrukturieren Es gibt quasi für jede Skript-/Programmiersprache parser. Gerade an einem Windowsrechner und kein Linux zur Hand? - Kein Problem, bearbeitet man die Json halt ganz easy mit Powershell (nativ). ...
|
|
matze31
(Themenstarter)
Anmeldungsdatum: 25. Oktober 2015
Beiträge: 836
|
Erstmal vielen dank für die schnellen und guten Antworten.
Nachdem ich mir eine Übersicht gemacht habe würde ich json bevorzugen.
Mit Json kann ich auch in Python arbeiten. Was ist das einfachste in der bash eine solche Datei mit Einträgen zu erstellen, bzw viel mehr einen bestimmten Wert zu lesen und auch zu überschreiben?
Es soll recht einfach gehalten werden.
Nehmen wir mal an, die Datei sieht dann so aus: {"Name":"Max", "Alter":"20","Wohnort":"Berlin"}
Ich möchte über das json iterieren und dann den Wert von den Schlüssel "Alter" ändern.
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17672
Wohnort: Berlin
|
TK87 schrieb: user_unknown schrieb: Wieso JSON? Ich sehe Json als geeignetes Format um Konstrukte, wie sie für objektorientierte Sprachen typisch sind, an
Das ist so nicht richtig (und dein Beispiel ist auch kein Json).
Mein Beispiel sollte auch kein Json sein, sondern Pseudocode, der geeignet ist, per Json dargestellt zu werden, weil er verästelt ist.
Json ist schlichtweg ein sehr leicht lesbares Format um Mehrdimensionale Tabellen und Listen darzustellen.
Nur das in der Frage weder von einer Tabelle, noch von Listen die Rede ist (und auch nicht von Bäumen). Und eine Reihe einfacher Zuweisungen ist natürlich noch leichter zu lesen:
| # conf.sh:
Name=Max
Alter=20
Wohnort=Berlin
|
Also eine Tabelle oder Liste, bei der jeder Zellwert/Listenpunkt wieder eine weitere Tabelle oder Liste sein kann (bis ins unendliche skalierbar).
YAGNI.
Wo ist der Vorteil gegenüber source, welches ein Buildin ist
Wo soll ich da bloß anfangen? Neben bereits erwähnten...
Beim ersten Vorteil, wenn es einen ersten Vorteil gibt.
War keine Anforderung.
diese Kategorisieren,
dito.
Alternativen hinzufügen,
dito.
oder was auch immer einem gerade vorschwebt.
Ach so.
Ist kein Vorteil, weil eine zeilenweise Wertzuweisung noch einfacher per Editor bearbeitbar ist.
Wie kann das einfacher sein, als zu schreiben "Alter=21"?
YAGNI. Von einem Format war gar nicht die Rede.
Für Schlüssel=Wert-Paare braucht man gar keinen Parser. Man spart sich also eine Abhängigkeit.
Gerade an einem Windowsrechner und kein Linux zur Hand? - Kein Problem, bearbeitet man die Json halt ganz easy mit Powershell (nativ).
Als ob Schlüssel-Wert-Paare unter Windows ein Problem wären. Bash war vorgegeben und unter Windows gibt es beispielsweise gitbash, falls man das doch auf Windows umziehen möchte. Auch da ist ein
wohl kaum von irgendwelcher Jsongymnastik zu überholen.
|
|
juribel
Anmeldungsdatum: 20. April 2014
Beiträge: 1326
|
Schon mal jemand an SQLite gedacht? Damit gehts doch viel einfacher!
|
|
TK87
Anmeldungsdatum: 8. Juli 2019
Beiträge: 303
Wohnort: Aachen
|
matze31 schrieb: Was ist das einfachste in der bash eine solche Datei mit Einträgen zu erstellen, bzw viel mehr einen bestimmten Wert zu lesen und auch zu überschreiben?
Es soll recht einfach gehalten werden.
Nehmen wir mal an, die Datei sieht dann so aus: {"Name":"Max", "Alter":"20","Wohnort":"Berlin"}
Ich möchte über das json iterieren und dann den Wert von den Schlüssel "Alter" ändern.
Bei dem Beispiel einfach
| json='{"Name":"Max", "Alter":"20","Wohnort":"Berlin"}'
jq 'select(.Name=="Max").Alter=21' <<<$json
|
Allerdings gibt es ja vermutlich mehrere Einträge, also dürfte wohl noch ein Array drum sein...
[{"Name":"Max", "Alter":20,"Wohnort":"Berlin"}]Das sähe dann so aus:
| jq '( .[] | select(.Name=="Max") ).Alter=21' <<<$json
|
Natürlich kann man auch nach mehreren Kriterien filtern...
| jq '( .[] | select(.Name=="Max" and .Wohnort=="Frankfurt") ).Alter=21' <<<$json
|
|
|
TK87
Anmeldungsdatum: 8. Juli 2019
Beiträge: 303
Wohnort: Aachen
|
user_unknown schrieb: Json ist schlichtweg ein sehr leicht lesbares Format um Mehrdimensionale Tabellen und Listen darzustellen.
Nur das in der Frage weder von einer Tabelle, noch von Listen die Rede ist (und auch nicht von Bäumen).
Wie shiro schon sagte: Da der TS sich etwas unklar ausgedrückt und Begriffe verwendet hat (z.B. dictionary), die eine definierte Bedeutung haben, ist es schwer zu erahnen, was er wirklich will.
user_unknown schrieb: Und eine Reihe einfacher Zuweisungen ist natürlich noch leichter zu lesen:
| # conf.sh:
Name=Max
Alter=20
Wohnort=Berlin
|
Genau da wären wir beim entscheidenden Punkt: Du hast jetzt einen Adressbucheintrag definiert. Was machst du beim zweiten? Und wenn du dann mehrere Einträge hast, wie filterst du nach Name, Wohnort, ..., um nur das Alter von Max zu ändern?
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1466
|
Schon mal jemand an SQLite gedacht? Damit gehts doch viel einfacher!
Yeah! Wenn man die einfache Lösung mit der flachen Datei nicht haben will sondern die komplexe Form einer .json Struktur bevorzugt, kann man auch SQLite3 verwenden. Ab der Version 3.38.0 kann "sqlite3" ja auch nativ mit json Strukturen arbeiten. Dann kann man herrlich SQL Syntax mit den json_* Funktionen verweben.
|
|
juribel
Anmeldungsdatum: 20. April 2014
Beiträge: 1326
|
Echt jetzt? Das ist ja interessant!
|