ubuntuusers.de

[Bash] while-Schleife mit Arrayauslese - Output verabeiten/clever gestalten

Status: Gelöst | Ubuntu-Version: Xubuntu
Antworten |

D630

Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

Hi,

nach Anleitung von/durch Jürgen Wolf bastel ich gerade an einer while-Schleife, mit der ich zum ersten Mal Feldvariablen auslese. Allerdings weiß ich gerade nicht, wie ich den Output weiterverarbeiten kann. Die Funktion sieht - noch ganz frisch - derzeit so aus:

 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
26
27
28
29
30
31
32
33
34
35
36
37
38
## Einen oder mehrere GLOSSA-Datensätze modifizieren: $ glossa-modify [ID/s] [tags:,] [quelle:] [begriff:] [bedeutung:]
function glossa-modify()
{

glossa-pref

array=( "$1" "$2" "$3" "$4" "$5" )


typeset -i i=1 max=${#array[*]}
while (( i < max ))
  do
    if [[ "$1" == *-* ]] && [[ "$1" == *,* ]]; then for j in $(glossa-parse-id "$1") ; do echo ""$j";"$(echo "${array[$i]}" | \ 
    sed -r 's#^(\<.)#\U\1#g')"" >> "$g_modi" ; done ; fi
    if [[ "$1" == *-* ]]; then ; do echo ; done ; fi
    if [[ "$1" == *,* ]]; then ; do echo ; done ; fi
    if [[ "$1" != *-* ]] && [[ "$1" != *,* ]]; then ; do echo ; done ; fi
    i=i+1
done

}

## GLOSSA-Parse-ID http://forum.ubuntuusers.de/topic/zeichenketten-aus-funktions-argument-auslesen-/
function glossa-parse-id()
{ 
eval "echo $(echo "$1" | sed -re 's#,# #g;s#([[:digit:]]+)-([[:digit:]]+)#{\1..\2}#g')"
}

## Einstellungen
function glossa-pref()
{
EDITOR=zile
g_dir=~/tmp/glossa # Glossa-dir
g_glos="$g_dir"/glossarium.csv # Glossa-databasefile
g_exp="$g_dir"/glossarium_exp.csv # Glossa-default-exportfile
g_edit="$g_dir"/glossarium_edit.csv # tmpfile
g_modi="$g_dir"/glossarium_modify.csv # tmpfile
}

So wie es jetzt ist, produziert glossa-modify() Dateien in dieser Form:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat ~/tmp/glossa/glossarium_modify.csv
1;Tags:test,versuch
2;Tags:test,versuch
3;Tags:test,versuch
4;Tags:test,versuch
5;Tags:test,versuch
1;Quelle:wiki
2;Quelle:wiki
3;Quelle:wiki
4;Quelle:wiki
5;Quelle:wiki
1;Begriff:array
2;Begriff:array
3;Begriff:array
4;Begriff:array
5;Begriff:array
1;Bedetung:feldvariable
2;Bedetung:feldvariable
3;Bedetung:feldvariable
4;Bedetung:feldvariable
5;Bedetung:feldvariable

die aber irgendwie so zurecht gemacht werden muss, dass sie in die Datenbank passt, die so aus aussieht:

1
2
3
4
5
6
$ cat ~/tmp/glossa/glossarium.csv | column -t -s ";"
Datum                ID  UUID                                  Quelle  Tags     Begriff  Bedeutung
2013-08-27_18:32:35  5   e7bb8e40-f75b-4bd7-96f6-4e4faef36768  wiki    versuch  karotte  gemuese
2013-08-27_18:32:52  4   347ed8ab-d1fb-4c44-925f-5e507d803b83  wiki    versuch  gurke    gemuese
2013-08-27_18:51:10  3   edeb7a50-588b-456b-afac-fe38c2273b59  wiki    test     apfel    obst
2013-08-27_19:09:37  6   44b86941-6197-4b2b-974d-efca9cd75fa7  wiki    test     birne    obst

Weiß jemand zufällig Rat, mit welchem kleinen Zaubertrick es schneller geht, als alles mit cut & co. zu schneiden/in neue Datein zu leiten!? Oder hat jemand einen Tipp, wie ich den Output vorzeitig geschickt vorbereiten kan?!

Gruß 🐸

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Vielleicht verrätst Du mal, wie die Daten angeliefert/eingelesen werden ? (also im Endeffekt, wie sie umformatiert werden sollen)
Aus Deinem Code werde ich jedenfalls nicht so richtig schlau, das ist mir zu chaotisch.

Ansonsten würde ich bei solchem Array-Zeug lieber awk (oder sonst eine Programmiersprache Deiner Wahl) und nicht ein Shellskript nehmen. Das ist wesentlich handlicher.

LG,

track

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

track schrieb:

Vielleicht verrätst Du mal, wie die Daten angeliefert/eingelesen werden ? (also im Endeffekt, wie sie umformatiert werden sollen)
Aus Deinem Code werde ich jedenfalls nicht so richtig schlau, das ist mir zu chaotisch.

Ansonsten würde ich bei solchem Array-Zeug lieber awk (oder sonst eine Programmiersprache Deiner Wahl) und nicht ein Shellskript nehmen. Das ist wesentlich handlicher.

LG,

track

Hi,

entschuldige, diesmal habe ich die Einleitung unter den Tisch fallen lassen. Danke, dass Du mich darauf hinweist. | Hier habe im Forum schon mal davon erzählt. Weil ich erst seit ein paar Wochen Shell Scripting lerne, habe ich mir zum Üben für die Bash 16 Funktionen erstellt, mit denen ich ein simples Glossar über die Kommandozeile verwalten kann.

Derzeit bestehen folgende Funktionen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ typeset -F | grep "glossa-" | cut -d " " -f3
glossa-add
glossa-delete
glossa-edit
glossa-export
glossa-filter
glossa-get
glossa-help
glossa-info
glossa-info-tags
glossa-ini
glossa-list
glossa-list-block
glossa-modify
glossa-parse-id
glossa-pref
glossa-test

Wie man sieht, habe ich bereits eine Funktion, mit der ich den Datensatz (einfache CSV-Datei) editieren kann: Mit der Funktion glossa-edit() benutze ich einen Editor, um die Daten zu bearbeiten. Aufgerufen wird diese mit glossa-edit [ID] oder glossa-edit [Begriff].

Nun habe ich mir überlegt, dass ich mit Feldvaribalen mehrere Daten mit einem Kommando bearbeiten könnte. Deswegen nun die o.g. genannte Funktion glossa-modify(). Aufgerufen wird diese/kann diese mit glossa-modify [IDs] [tags:] [quelle:] [begriff:] [bedeutung:]. Also zB glossa-modify 1,3-5 tags:obst,gemuese quelle:wiki. Damit sollen die entsprechenden Datenfelder modifiziert werden.

Ich habe heute das erste Mal Arrays angwendet. Das Output-File zeigt in der ersten Spalte die ID-Nummern, die mit glossa-modify angegeben wurden; die zweite Spalte zeigt die Argumente tags:, quelle:, begriff: und bedeutung. Es ließen sich außerdem noch die anderen Feldtitel aus der Datenbank anwenden: Datum und UUID, was wohl aber keinen Sinn macht, da diese nicht selbstständig modifiziert werden sollen.

Meine Hauptfrage: Wie kann ich den Output, der durch die Funktion produziert wird, mit einfachsten Mitteln schnell zurechtbiegen?! Da das Ganze ja in die Funktion soll, um Shell zu lernen, wäre es interessant, wenn jemand mit dem einen oder anderen sed/awk/perl-Zaubertrick aufwarten könnte. Zurechtbiegen muss wohl heißen: nur noch 5 Zeilen; pro ID eine; die Zeilen beinhalten die angebenen/zugehörigen Felder. D.h., diese so aufbereiten und umformatieren, dass sie einfacher in die Datenbank aufgenommen werden können, bzw. so, dass die alten Datenfelder entfernt werden können.

Das Ziel der Funktion: die mit dem Kommando angebenen Argumente auslesen, um mehrere Felder in der Datenbank zu modifizieren/aktualisieren.

Zum Vergleich im Anhang die Funktion glossa-edit().

glossa-edit (1.0 KiB)
glossa-edit
Download glossa-edit

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

D630 schrieb:

(Ist noch eine Antwort zur Anfangsfrage, vor Lesen der Track- und der Rückantwort)

1
2
3
4
5
    if [[ "$1" == *-* ]] && [[ "$1" == *,* ]]; then for j in $(glossa-parse-id "$1") ; do echo ""$j";"$(echo "${array[$i]}" | \ 
    sed -r 's#^(\<.)#\U\1#g')"" >> "$g_modi" ; done ; fi
    if [[ "$1" == *-* ]]; then ; do echo ; done ; fi
    if [[ "$1" == *,* ]]; then ; do echo ; done ; fi
    if [[ "$1" != *-* ]] && [[ "$1" != *,* ]]; then ; do echo ; done ; fi

In Skripten zwängt man selten mehrere Befehle in eine Zeile sondern freut sich, dass die Einrückung mit den Zeilenumbrüchen die Struktur des Programms für das Auge sichtbar macht.

if-then-do-done-fi kannte ich bislang noch nicht - hat das Vorteile gegenüber dem schlankeren if-then-fi?

die aber irgendwie so zurecht gemacht werden muss, dass sie in die Datenbank passt, die so aus aussieht:

1
2
3
$ cat ~/tmp/glossa/glossarium.csv | column -t -s ";"
Datum                ID  UUID                                  Quelle  Tags     Begriff  Bedeutung
2013-08-27_18:32:35  5   e7bb8e40-f75b-4bd7-96f6-4e4faef36768  wiki    versuch  karotte  gemuese

Wo kommen denn die Daten her?

Weiß jemand zufällig Rat, mit welchem kleinen Zaubertrick es schneller geht, als alles mit cut & co. zu schneiden/in neue Datein zu leiten!? Oder hat jemand einen Tipp, wie ich den Output vorzeitig geschickt vorbereiten kan?!

Wieviele Datensätze hast Du denn zur Zeit, wie lange dauert es, und welche Zeitdauer strebst Du an?

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

user unknown schrieb:

In Skripten zwängt man selten mehrere Befehle in eine Zeile sondern freut sich, dass die Einrückung mit den Zeilenumbrüchen die Struktur des Programms für das Auge sichtbar macht. if-then-do-done-fi kannte ich bislang noch nicht - hat das Vorteile gegenüber dem schlankeren if-then-fi?

Ai Ai, das war eigentlich - eigentlich waren diese von dir genannten Zeilen noch nicht auskommentiert. Deswegen u.a. so chaotisch. Ich muss mich wohl mal dringend schlau machen, wie ich hier den Code handlicher hineinkopieren kann, ohne Formatverzehrungen etc. Die Rauten hatte ich selbst aber vergessen! Sorry! Gezeigt werden sollte nur die erste If-Anweisung, die anderen sollen nach demselben Muster ablaufen, sobald ich die Geschichte mit dem Output geregelt habe.

die aber irgendwie so zurecht gemacht werden muss, dass sie in die Datenbank passt, die so aus aussieht:

1
2
3
$ cat ~/tmp/glossa/glossarium.csv | column -t -s ";"
Datum                ID  UUID                                  Quelle  Tags     Begriff  Bedeutung
2013-08-27_18:32:35  5   e7bb8e40-f75b-4bd7-96f6-4e4faef36768  wiki    versuch  karotte  gemuese

Wo kommen denn die Daten her?

Die werden mit glossa-add() in die Datenbank "$g_glos" geschrieben.

Weiß jemand zufällig Rat, mit welchem kleinen Zaubertrick es schneller geht, als alles mit cut & co. zu schneiden/in neue Datein zu leiten!? Oder hat jemand einen Tipp, wie ich den Output vorzeitig geschickt vorbereiten kan?!

Wieviele Datensätze hast Du denn zur Zeit, wie lange dauert es, und welche Zeitdauer strebst Du an?

Nur für Übungszwecke. Wobei es aber doch sehr angenehm ist, Kurznotizen etc. per Kommandozeile zu erstellen ☺

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

Ich passe mal schnell die Zeilen oben an.

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

Ok geht nicht.

 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
26
27
## Einen oder mehrere GLOSSA-Datensätze modifizieren: $ glossa-modify [ID/s] [tags:,] [quelle:] [begriff:] [bedeutung:]

function glossa-modify()
{
glossa-pref

array=( "$1" "$2" "$3" "$4" "$5" )

typeset -i i=1 max=${#array[*]}

while (( i < max ))
do

  if [[ "$1" == *-* ]] && [[ "$1" == *,* ]]
    then for j in $(glossa-parse-id "$1")
    do 
      echo ""$j";"$(echo "${array[$i]}" | sed -r 's#^(\<.)#\U\1#g')"" >> "$g_modi"
    done
  fi

  #if [[ "$1" == *-* ]]; then ; do echo ; done ; fi
  #if [[ "$1" == *,* ]]; then ; do echo ; done ; fi
  #if [[ "$1" != *-* ]] && [[ "$1" != *,* ]]; then ; do echo ; done ; fi

  i=i+1
done
}

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

Wir kennen ja nun Dein glossa-System nicht (gab es da nicht mal einen dt. Schlagerfuzzi, zumindest einen, der in Deutschland viele seiner Taten verübte, der 'Glossa, Glossa' gesungen hat - oft kamen die ja aus dem Ausland 'Glossa Mexicana').

Was erwartest Du, ist ein beispielhafter, aussagekräftiger Inhalt für das folgende Array?

1
array=("$1" "$2" "$3" "$4" "$5")

Und was für die Rückgabe von glossa-parse-id?

Was soll die Funktion machen? Gib mal ein Beispiel!

Optimieren kann man kein Programm ohne definiertes Ziel, denn fast immer läßt sich mit mehr und mehr Aufwand noch mehr optimieren. Es ist vollkommen sinnlos ohne zu messen, wie lange etwas jetzt dauert, überhaupt anzufangen zu optimieren, weil man wahrscheinlich nicht herausfindet, ob es überhaupt geglückt ist.

Bei Datenmengen im Hobbybereich zu Beginn eines jungen Programms ist wahrscheinlich gar kein Unterschied messbar.

Deine Ziele sollten ein verständliches, übersichtlich strukturiertes Programm sein, welches fehlerfrei, erweiterbar und robust ist. Das sind Designziele die üblicherweise im Konflickt stehen mit Optimierungen.

Von Tricks, vor allem von Zaubertricks solltest Du Dich fernhalten. Tricks ist nur ein anderes Wort für sich spektakulär in den eigenen Fuß zu schießen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

Einrückung geht übrigens so (nein, so geht es nicht, bzw. Inyoka, die CS-Software des Forums ist da kaputt. Im Editor sieht es noch richtig aus und womöglich wenn Du meinen Beitrag zitierst wieder für die Zeit des Editierens, bzw. wenn Du es dann in Deinen Editor kopierst):

 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
26
27
28
29
30
31
32
33
## Einen GLOSSA-Datensatz editieren
function glossa-edit()
{
	glossa-pref

	if [[ "$1" != [0-9]*-* ]] && [[ "$1" != *[äüöß\;ÄÖÜ]* ]]
	then
		if [ $1 ]
		then
			grep -q ";$1;" "$g_glos"
			if [ $? = "0" ]
			then				
				grep ";$1;" "$g_glos" | cut -d ";" -f 2-7 | sed "s#^#$(date +%Y-%m-%d_%H:%M:%S);#g" > "$g_edit"
				md5_pre=$(md5sum "$g_edit")
				$EDITOR "$g_edit"
				md5_post=$(md5sum "$g_edit")
				if [ "$md5_pre" != "$md5_post" ]
				then
					sed -i /";$1;"/d "$g_glos" && cat "$g_glos" "$g_edit" >> "$g_glos.$$" && sort -g "$g_glos.$$" | uniq > "$g_glos" && rm "$g_edit" "$g_glos.$$"
					echo "Datensatz ediert."
				else
					echo "Datensatz wurde nicht bearbeitet und somit nicht veraendert."
				fi
			else
				echo "Angabe kann nicht verarbeitet werden, no matching!"
			fi
		else
			echo "Bitte eine Angabe machen..." 
		fi
	else
		echo "Es muss eine PASSENDE Angabe gemacht werden! Gib 'ID' oder 'Begriff' an, und das unter Verzicht auf die untersagten Sonderzeichen und Umlaute."
	fi		
}

Vielleicht ist es bei Dir ja auch richtig, solange Du es schreibst. ☺

if/then ist ein zusammenhängender Ausdruck. Möglich wäre noch, das then miteinzurücken, aber dann das, was im Block steht nicht nochmal einrücken:

1
2
		if [ $1 ]
			then grep -q ";$1;" "$g_glos"

Der Parameter Deiner Funktion ist nirgends dokumentiert. Wenn Du gleich als erstes einen sinnvolen Namen einführst kann man verstehen, was Du tust oder tun willst.

1
2
3
4
5
6
7
8
9
function demo()
{
	datum=$1
	id=$2
	uuid=$3
	quelle=$4
	tags=$5

	array=("$datum" "$id" "$uuid" "$quelle" "$tags")

$1 versteht kein Mensch.

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

user unknown schrieb:

Wir kennen ja nun Dein glossa-System nicht (gab es da nicht mal einen dt. Schlagerfuzzi, zumindest einen, der in Deutschland viele seiner Taten verübte, der 'Glossa, Glossa' gesungen hat - oft kamen die ja aus dem Ausland 'Glossa Mexicana').

Hehe, ja, aber der bin nicht ich! 😉

Was erwartest Du, ist ein beispielhafter, aussagekräftiger Inhalt für das folgende Array?

1
array=("$1" "$2" "$3" "$4" "$5")

Und was für die Rückgabe von glossa-parse-id?

Was soll die Funktion machen? Gib mal ein Beispiel!

Also, ich habe mir jetzt nochmal Gedanken gemacht - und mir überlegt, dass es einfacher ist, keine Arrays zu benutzen. Ziel von der Funktion rexgildo-modify() soll es sein, die Datenbankfelder aus der CSV-Datei nicht mit einem Texteditor zu bearbeiten, wie ich es ja bereits mit der Funktion glossa-edit() mache, sondern mehrere Argumente und deren Stringangaben zu benutzen, um mehrer Datensätze, die denselben Feldinhalt haben, mit einem Kommando verändern zu können. Im Grunde genommen will ich einfach nur eine CSV-Datei über die Kommandozeile verwalten und manipulieren. Weil ich doch schnell gemerkt habe, dass das gar nicht mal so einfach ist, sollen mit dieser Funktion erstmal nur die Datenfelder "Tags" und "Quelle" bearbeitet werden. Identifiziert werden sie durch das Datenfeld "ID". Dabei soll gelten:

  • $1 muss "ID" sein

  • werden $2 und $3 gleichzeitig benutzt, ist $2="Quelle" und $3="Tags"

  • wird nur $2 angegeben, darf es "Quelle" oder "Tags" sein.

Der Befehl soll also zB so lauten: glossa-modify 2-10 quelle:forum tags:array,feldvariable. Die "ID" kann nach diesen Mustern angegeben werden: "5-10,13" oder "1-4,6-13,20", "5-10", "1,4,6,8" oder "22".

Einen groben Rahmen habe ich mir jetzt gehämmert, in dem es auch schon funktioniert. Aber wie man sehen kann, gibts ein bisschen sehr viel File-Produzieren und doppelte Befehle. Die Schwierigkeiten sind: damit klarkommen, dass die Argumente nicht in derselben Reihenfolge folgen müssen (auch wenn es nur zwei sind); sich mit sed und awk auszukennen; und deswegen eben auch, die neuen Datenfelder an den passenden Ort in die Datenbank zu bekommen. Die ganze Textmanipulationsgeschichte ist sehr zeitaufwändig, finde ich. Aber eben auch spannend.

Also so in der Art sieht es derzeit aus. Work in progress:

 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
## Einen oder mehrere GLOSSA-Datensätze modifizieren
function glossa-modify()
{

glossa-pref

g_modi="$g_dir"/glossarium_modify.csv # tmpfile
g_modi_sp67="$g_dir"/glossarium_modify_sp67.csv # tmpfile
g_modi_sp5="$g_dir"/glossarium_modify_sp5.csv # tmpfile

id="$1"

# Optionen für cut vorbereiten bzw. Variablen definieren
if [[ "$2" == quelle:* ]] && [[ "$3" == tags:* ]]
	then
		cutcol=$(echo "-f2,3")
		echo "beides"

	elif [[ "$2" == quelle:* ]] && [ "$#" -eq 2 ]
		then
			echo "nur quelle"
			cutcol=$(echo "-f2,3")
			cuttags=$(echo "-f5")
		else
			echo "nur tags"
			cutcol=$(echo "-f2,3,4")
fi

# Argumente in einer for-Schleife auslesen; Datenfelder/-sätze identifizieren und mit grep und cut aus der DB extrahieren
if [[ "$id" == *-* ]] && [[ "$id" == *,* ]] # ID-Schreibung: zB "5-10,13" oder "1-4,6-13,20" usw.
	then
		for i in $(glossa-parse-id "$id") # "5-10,13" wird zu "5 6 7 8 9 10 11 12 13" usw.
			do
				echo "$i $2 $3" | sed -r 's# #;#g;s#[[:alnum:]]+:##g;s#;$##' >> "$g_modi" # Strings der Argumente in Datei leiten
				grep ";$i;" "$g_glos" | cut -d";" "$cutcol" >> "$g_modi.$$" && # anhand der IDs die passenden Datensätze/Zeilen aus DB holen und speichern
				if [[ "$2" == quelle:* ]] && [ "$#" -eq 2 ] 
					then
						grep ";$i;" "$g_glos" | cut -d";" "$cuttags" | sed -r 's#$#;#' >> "$g_modi_sp5"
				fi
				grep ";$i;" "$g_glos" | cut -d";" -f6,7  >> "$g_modi_sp67" &&
				sed -i /";$i;"/d "$g_glos" # alte Datensätze aus der DB löschen
	  	done
	else
		echo "Test 1,2,3"
fi
	# Andere ID-Schreibung berücksichtigen: zB "5-10", "1,4,6,8" oder "22"
	#if [[ "$A" == *-* ]]; then ; do ; done ; fi
	#if [[ "$A" == *,* ]]; then ; do ; done ; fi
	#if [[ "$A" != *-* ]] && [[ "$A" != *,* ]]; then ; do ; done ; fi

# Die neue/modifizierte Datensätze wieder in die DB bekommen.
join -t ";" -1 1 -2 1 "$g_modi.$$" "$g_modi" > "$g_glos.$$" &&

if [[ "$2" == quelle:* ]] && [ "$#" -eq 2 ]
	then
		echo "nur quelle"
		paste -d ";" "$g_glos.$$" "$g_modi_sp5" > "$g_modi.$$" &&
		paste -d ";" "$g_modi.$$" "$g_modi_sp67" | sed "s#^#$(date +%Y-%m-%d_%H:%M:%S);#g" | tr -s ';' > "$g_glos.$$" &&
		cat "$g_glos" "$g_glos.$$" >> "$g_glos" 2>>/dev/null
		sort -g "$g_glos" | uniq > "$g_glos.$$" &&
		mv "$g_glos.$$" "$g_glos" &&
		rm "$g_modi" "$g_modi.$$" "$g_modi_sp67" "$g_modi_sp5"
	else
		echo "tags oder beides"
		paste -d ";" "$g_glos.$$" "$g_modi_sp67" | sed "s#^#$(date +%Y-%m-%d_%H:%M:%S);#g" > "$g_modi"
		cat "$g_glos" "$g_modi" > "$g_modi.$$" &&
		sort -g "$g_modi.$$" | uniq > "$g_glos"
		rm "$g_modi" "$g_modi.$$" "$g_modi_sp67" "$g_glos.$$"
fi

}

Gruß 🐸

D630

(Themenstarter)
Avatar von D630

Anmeldungsdatum:
24. Juli 2013

Beiträge: 329

Hossa!

Ich habe die Funktion nun nochmal umgebaut und benutze im dritten Teil das Perl-Programm super-cut aka scut von Harry Mangalam. Damit lassen sich u.a. Spalten ausschneiden und gleichzeitig sortieren. Das erspart mehrmalige cut/paste-Befehle.

Gegeben sei diese Datenbank:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ cat glossarium.csv
Datum;ID;UUID;Quelle;Tags;Begriff;Bedeutung
2013-09-16_19:20:47;1;f4088523-49e7-475c-b9cb-6a7add90302a;wikipedia;nahrungsmittel,gemuese;apfel;pyrus
2013-09-16_19:20:47;2;388d39b6-54fc-4591-8547-adecb974a618;wikipedia;nahrungsmittel,gemuese;birne;malus
2013-09-16_19:20:47;3;d339ea3e-0ade-44e5-84e3-8d8c8722c79c;wikipedia;nahrungsmittel,gemuese;banane;musa
2013-09-16_19:20:47;4;8571e0ba-7320-4709-8469-c2f546754bc8;wikipedia;nahrungsmittel,gemuese;kiwi;actinidia deliciosa
2013-09-16_19:20:47;5;14c2fa51-4b22-4e8d-aeba-162e5f6a29ad;wikipedia;nahrungsmittel,gemuese;kartoffel;solanum tuberosum

$ glossa-list
Datum                ID  UUID                                  Quelle     Tags                    Begriff
2013-09-16_19:20:47  1   f4088523-49e7-475c-b9cb-6a7add90302a  wikipedia  nahrungsmittel,gemuese  apfel
2013-09-16_19:20:47  2   388d39b6-54fc-4591-8547-adecb974a618  wikipedia  nahrungsmittel,gemuese  birne
2013-09-16_19:20:47  3   d339ea3e-0ade-44e5-84e3-8d8c8722c79c  wikipedia  nahrungsmittel,gemuese  banane
2013-09-16_19:20:47  4   8571e0ba-7320-4709-8469-c2f546754bc8  wikipedia  nahrungsmittel,gemuese  kiwi
2013-09-16_19:20:47  5   14c2fa51-4b22-4e8d-aeba-162e5f6a29ad  wikipedia  nahrungsmittel,gemuese  kartoffel

Sowie die Funktionen glossa-pref() und glossa-parse-id():

1
2
3
4
5
6
7
8
9
function glossa-pref()
{
EDITOR=zile
g_dir=~/tmp # Glossa-dir
g_glos="$g_dir"/glossarium.csv # Glossa-databasefile
g_exp="$g_dir"/glossarium_exp.csv # Glossa-default-exportfile
g_edit="$g_dir"/glossarium_edit.csv # tmpfile
g_modi="$g_dir"/glossarium_modify.csv # tmpfile
}
1
2
3
4
function glossa-parse-id()
{
eval "echo $(echo "$1" | sed -re 's#,# #g;s#([[:digit:]]+)-([[:digit:]]+)#{\1..\2}#g')";
}

Dann erhalte ich zB mit:

1
2
3
4
5
6
7
8
$ glossa-modify 1-4 quelle:brockhaus tags:nahrungsmittel,obst
$ glossa-list
Datum                ID  UUID                                  Quelle     Tags                    Begriff
2013-09-16_19:20:47  5   14c2fa51-4b22-4e8d-aeba-162e5f6a29ad  wikipedia  nahrungsmittel,gemuese  kartoffel
2013-09-16_19:39:24  1   f4088523-49e7-475c-b9cb-6a7add90302a  brockhaus  nahrungsmittel,obst     apfel
2013-09-16_19:39:24  2   388d39b6-54fc-4591-8547-adecb974a618  brockhaus  nahrungsmittel,obst     birne
2013-09-16_19:39:24  3   d339ea3e-0ade-44e5-84e3-8d8c8722c79c  brockhaus  nahrungsmittel,obst     banane
2013-09-16_19:39:24  4   8571e0ba-7320-4709-8469-c2f546754bc8  brockhaus  nahrungsmittel,obst     kiwi

Der Code von glossa-modify() sieht jetzt so aus:

 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
function glossa-modify()
{

glossa-pref

id="$1"

# Optionen für scut vorbereiten bzw. Variablen definieren
if [ "$#" -eq 3 ] && [[ "$2" == quelle:* ]] && [[ "$3" == tags:* ]]
then
    scut_col="0 1 6 7 4 5"

elif [ "$#" -eq 2 ] && [[ "$2" == quelle:* ]]
then
    scut_col="0 1 6 3 4 5"
				
elif [ "$#" -eq 2 ] && [[ "$2" == tags:* ]]
then
    scut_col="0 1 2 6 4 5"
else
    echo "Argumente bitte korrekt angeben."
    return 0
fi

# Argumente in einer for-Schleife auslesen; Datenfelder/-sätze identifizieren und mit grep und cut aus der DB extrahieren
if [[ "$id" == *-* ]] && [[ "$id" == *,* ]]
then
    for i in $(glossa-parse-id "$id") # "5-10,13" wird zu "5 6 7 8 9 10 11 12 13" usw.
    do
	echo "$i $2 $3" | sed -r 's# #;#g;s#[[:alnum:]]+:##g;s#;$##' >> "$g_modi"
	grep ";$i;" "$g_glos" | cut -d";" -f2-7 >> "$g_modi.$$" &&
	sed -i /";$i;"/d "$g_glos"
    done

elif [[ "$id" == *-* ]]
then
    x_y=$(echo "$id" | sed s/"-"/".."/g)
    for k in $(eval echo {"$x_y"})
    do
	echo "$k $2 $3" | sed -r 's# #;#g;s#[[:alnum:]]+:##g;s#;$##' >> "$g_modi"
	grep ";$k;" "$g_glos" | cut -d";" -f2-7 >> "$g_modi.$$" &&
	sed -i /";$k;"/d "$g_glos"
    done

elif [[ "$id" == *,* ]]
then
    for m in $(eval echo {"$id}")
    do
	echo "$m $2 $3" | sed -r 's# #;#g;s#[[:alnum:]]+:##g;s#;$##' >> "$g_modi"
	grep ";$m;" "$g_glos" | cut -d";" -f2-7 >> "$g_modi.$$" &&
	sed -i /";$m;"/d "$g_glos"
    done
else
    echo "Bitte eine korrekte ID-Angabe machen."
    return 0
fi

# Die neuen/modifizierten Datensätze wieder in die DB bekommen.
join -t ";" -1 1 -2 1 "$g_modi.$$" "$g_modi" > "$g_glos.$$"
scut --id1=';' --od=';' --c1="$scut_col" < "$g_glos.$$" > "$g_modi.$$" 2>/dev/null
sed -i "s#^#$(date +%Y-%m-%d_%H:%M:%S);#g" "$g_modi.$$"
cat "$g_glos" "$g_modi.$$" | sort -g | uniq > "$g_glos"
rm "$g_modi" "$g_modi.$$" "$g_glos.$$"

}

Ich mache hier mal zu.

Gruß 🐸

Antworten |