wxpte
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1175
Wohnort: Schäl Sick
|
Hallo Community, ich arbeite mit zwei Hauptskripten, welche beide auf ein Subskript zugreifen. Das mache ich, weil es in beiden Hauptskripten einen Teil gibt, der identisch sein soll, und den ich bei Änderungen nur einmal bearbeiten will. Zum Weiterreichen von Daten behelfe ich mir derzeit mit Temporärdateien. Aber geht das auch direkt über Variablen? Hier die Skripte, um die es geht: 1. Hauptskript:
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 | #!/bin/bash
if [ $# -ne 1 ]; then
echo; echo "Verwendung: $0 '(StaffelxEpisode);Name des Titels'"; echo; exit; fi
./sub_1_3_serienpflege.sh
read dn < dn
read luecke < luecke
rm dn luecke
if [ "$dn" = 'Eingabe ungültig.' ]; then
echo $dn; echo; exit; fi
if fgrep -q "$1" $dn.ugf; then
echo 'Die Folge wurde schon als ungesehen registriert. Falsches Skript?'; exit
elif ! fgrep -q "$1" $dn.txt; then
echo 'Diese Folge befindet sich nicht in der Ausstrahlungsliste. Falsche Auswahl?'; exit; fi
epinr=$(echo "$1" | cut -f1 -d\;)
if fgrep -q "$epinr" $dn.rfl; then
sed -i "/$epinr/c$1" $dn.rfl
elif [ -n "$luecke" ]; then
sed -i "/$luecke/i$1" $dn.rfl
else echo "$1" >> $dn.rfl; fi
tag=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f3 | cut -d\. -f1)
mon=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f3 | cut -d\. -f2)
azeit=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f4 | sed 's/ Uhr//' | sed 's/\./:/')
ezeit=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f5 | sed 's/ Uhr//' | sed 's/\./:/')
if [ $(date +%m) -gt $mon ]; then
jahr=$(date -d 'next year' +%Y)
else jahr=$(date +%Y); fi
calcdatum=$(date -d "${jahr}-${mon}-${tag} 12:00" '+%s')
if [ $(date -d "$ezeit" +%s) -lt $(date -d "$azeit" +%s) ]; then
calcdatum=$(($calcdatum + 86400)); fi
termin=$(date -d "@$calcdatum" '+%Y-%m-%d')
echo "$termin $ezeit;$1;" >> $dn.ugf && echo 'Bestätigt.'; echo
|
2. Hauptskript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #!/bin/bash
if [ $# -ne 1 ]
then
echo; echo "Verwendung: $0 '(StaffelxEpisode);Name des Titels'"; echo
exit
fi
./sub_1_3_serienpflege.sh
read dn < dn
read luecke < luecke
rm dn luecke
if [ "$dn" = 'Eingabe ungültig.' ]; then
echo $dn; echo; exit; fi
if ! fgrep -q "$1" $dn.ugf 2> /dev/null; then
echo 'Diese Folge wurde nicht als ungesehen eingetragen. Falsche Auswahl?'; echo
else sed -i "/$1/d" $dn.ugf && echo 'Bestätigt.'; echo; fi
|
Subskript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | #!/bin/bash
echo "Welche Serie?"
echo -e "\t1 = Detektiv Conan | 2 = Inuyasha | 3 = Konosuba | 4 = One Punch Man"
read -p "=> " ser
case $ser in
1) echo 'Detektiv_Conan' > dn
> luecke
;;
2) echo 'Inuyasha' > dn
echo 'Banryuu gegen die Windnarbe' > luecke
;;
3) echo 'Konosuba' > dn
> luecke
;;
4) echo 'One_Punch_Man' > dn
> luecke
;;
*) echo 'Eingabe ungültig.' > dn
> luecke
;;
esac
|
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8616
Wohnort: Münster
|
wxpte schrieb: […] Zum Weiterreichen von Daten behelfe ich mir derzeit mit Temporärdateien. Aber geht das auch direkt über Variablen?
Über Variablen ist nur eine eingeschränkte Kommunikation in einer Richtung möglich: Jedes Programm kann einem von ihm gestarteten Programm über die Programmumgebung (environment) Informationen geben. Dazu benutzt man Umgebungsvariablen. Generell können zwei Programme über Dateien kommunizieren. Das können auch unbenannte oder benannte Pipelines sein. Eine weitere Möglichkeit sind Netzwerkverbindungen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12821
|
wxpte schrieb:
ich arbeite mit zwei Hauptskripten, welche beide auf ein Subskript zugreifen. Das mache ich, weil es in beiden Hauptskripten einen Teil gibt, der identisch sein soll, und den ich bei Änderungen nur einmal bearbeiten will. Zum Weiterreichen von Daten behelfe ich mir derzeit mit Temporärdateien. Aber geht das auch direkt über Variablen?
Nein, Umgebungsvariablen werden immer nur vom Elter zum Kind vererbt.
Hier die Skripte, um die es geht:
Die Skripte sind total unleserlich, weil sie weder Leerzeilen noch Einrückungen und Kommentare verwenden. Deshalb werde ich mir das nicht näher anschauen. Ein flüchtiger Blick verrät auch, dass Da da jede Menge Redundanz drin hast, z.B. die wiederholten Vorkommen von fgrep -m1 "$1" $dn.txt .
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Generell könntest du dir überlegen, ob du die "Subskripte" nicht sourcen kannst statt sie in einer Subshell auszuführen.
Ansonsten musst du die Subskripte halt etwas auf stdout zurückgeben lassen und das verwerten. Also z.B. entweder:
| #!/bin/bash
# Haupskript
source subskript.sh
echo "$foo"
|
Oder
| #!/bin/bash
# Hauptskript
foo=$(./subskript.sh)
echo "$foo"
|
| #!/bin/bash
# subskript.sh
echo "bar"
|
|
wxpte
(Themenstarter)
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1175
Wohnort: Schäl Sick
|
Erst einmal vielen Dank für die Infos. seahawk1986 schrieb: Generell könntest du dir überlegen, ob du die "Subskripte" nicht sourcen kannst statt sie in einer Subshell auszuführen.
Das scheint mir eine gute Lösung zu sein, ich werde es die nächsten Tage mal durchprobieren. user:seahawk1986:] schrieb: Ansonsten musst du die Subskripte halt etwas auf stdout zurückgeben lassen und das verwerten.
Damit kann man aber maximal einen Wert zurückgeben lassen, oder übersehe ich da etwas? rklm schrieb: Die Skripte sind total unleserlich, weil sie weder Leerzeilen noch Einrückungen und Kommentare verwenden.
Ich weiß, mit dem Schreiben von Kommentaren tue ich mich immer noch etwas schwer. Da werde ich bei der nächsten Frage meine Skripte noch nachträglich mit Kommentaren ausstatten müssen (falls ich wieder etwas fragen müsste). Ansonsten habe ich mir auch schon vorgenommen, zukünftig mit Auto-Indent bei vim zu arbeiten; ich werde nur die Einrückungsweite noch ein wenig reduzieren müssen. Das scheint in irgendeiner Umgebungsvariable hinterlegt zu sein. rklm schrieb: Ein flüchtiger Blick verrät auch, dass Da da jede Menge Redundanz drin hast, z.B. die wiederholten Vorkommen von fgrep -m1 "$1" $dn.txt .
Problem erkannt. Vermutlich ist der Ausweg, hier mit Arrays zu arbeiten.
|
wxpte
(Themenstarter)
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1175
Wohnort: Schäl Sick
|
Das Sourcen des Subskripts war genau das, wonach ich gesucht habe. Nochmals danke.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
wxpte schrieb: user:seahawk1986:] schrieb: Ansonsten musst du die Subskripte halt etwas auf stdout zurückgeben lassen und das verwerten.
Damit kann man aber maximal einen Wert zurückgeben lassen, oder übersehe ich da etwas?
Serialisierung - solange sich das Subskript und das aufrufende Skript auf ein Datenformat einigen können, kann man da beliebig viele Werte übergeben - ob das jetzt durch Zeilenumbrüche oder andere Trennzeichen aufsplitbare Strings sind, JSON oder explizite Wertzuweisungen für Variablen - z.B. für letzteres:
| #!/bin/bash
. <(./subskript.sh)
echo "$foo" "$spam" "${myarray[@]}"
|
| #!/bin/bash
# subskript.sh
foo="bar"
spam="ham"
myarray=(1 2 3 4 5)
typeset -p foo spam myarray
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Die fehlenden Einrückungen haben auch mich verschreckt. Das Subscript kann man mit einem Array kürzer gestalten:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | #!/bin/bash
echo "Welche Serie?"
ser=("dummy" "Detektiv Conan" "Inuyasha" "Konosuba" "One Punch Man")
for i in {1..4}
do
echo -ne "$i: ${ser[$i]}\t"
done
echo
read -p "=> " idx
case $idx in
1|2|3|4)
echo "${ser[$idx]}" > dn
> luecke
;;
*)
echo 'Eingabe ungültig.' > dn
> luecke
;;
esac
|
Da könnte man desweiteren die Arraylänge verwenden und ein if/else, um bei Verlängerung des Arrays nicht auch die case-Anweisung anfassen zu müssen. Aber bevor man sich da verzettelt springt man gleich zum weniger bekannten select-Schlüsselwort: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #!/bin/bash
echo "Welche Serie?"
ser=("Detektiv Conan" Inuyasha Konosuba "One Punch Man")
select auswahl in "${ser[@]}"
do
if ((REPLY > 0 && REPLY <= ${#ser[@]}))
then
echo "$auswahl" > dn
> luecke
break
else
echo Eingabe ungültig. > dn
> luecke
fi
done
|
Mit Ctrl-D kann man vorzeitig abbrechen.
|
wxpte
(Themenstarter)
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1175
Wohnort: Schäl Sick
|
Rückmeldung: das Sourcen des Subskripts funktioniert einwandfrei. Hier nochmal das Ergebnis, diesmal gegliedert und kommentiert: 1. Hauptskript
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 | #!/bin/bash
# Dem Skript muss genau ein Parameter mitgegeben werden, Prüfung
if [ $# -ne 1 ]; then
echo; echo "Verwendung: $0 '(StaffelxEpisode);Name des Titels'"; echo; exit
fi
# Subskript wird gesourced
source sub_1_3_serienpflege.sh
# Abbruch, wenn Eingabe im Subskript ungültig ist
if [ "$dn" = 'Eingabe ungültig.' ]; then
echo $dn; echo; exit
fi
# Ausstieg, wenn die Bedienung des Skripts sachlich falsch ist
if fgrep -q "$1" $dn.ugf; then
echo 'Die Folge wurde schon als ungesehen registriert. Falsches Skript?'; exit
elif ! fgrep -q "$1" $dn.txt; then
echo 'Diese Folge befindet sich nicht in der Ausstrahlungsliste. Falsche Auswahl?'; exit
fi
# Einsortierung in die Registrierliste
epinr=$(echo "$1" | cut -f1 -d\;) # Episodenbezeichnung wird in Variable hinterlegt
if fgrep -q "$epinr" $dn.rfl; then
sed -i "/$epinr/c$1" $dn.rfl # Eintrag mit Episodenbezeichnung existiert, Titel wird angepasst
elif [ -n "$luecke" ]; then
sed -i "/$luecke/i$1" $dn.rfl # noch fehlende Staffel wird oberhalb des Suchmusters $luecke eingefügt
else
echo "$1" >> $dn.rfl
fi
# Noch ungesehene Serienfolgen werden in die Liste eingetragen
tag=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f3 | cut -d\. -f1) # Tag der ersten Ausstrahlung in der Ausstrahlungsliste
mon=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f3 | cut -d\. -f2) # entsprechend für den Monat
azeit=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f4 | sed 's/ Uhr//' | sed 's/\./:/') # Zeit des Ausstrahlungsbeginns
ezeit=$(fgrep -m1 "$1" $dn.txt | cut -d\; -f5 | sed 's/ Uhr//' | sed 's/\./:/') # Zeit des Ausstrahlungsendes
if [ $(date +%m) -gt $mon ]; then # Jahr der Ausstrahlung sinnvoll ergänzen
jahr=$(date -d 'next year' +%Y) # Beispiel: aktueller Monat: 12, Monat der Ausstrahlung: 01
else
jahr=$(date +%Y)
fi
# ermitteltes Datum wird in ein berechenbares Format umgewandelt
# 12:00, damit es bei der Umstellung Sommerzeit/Nomalzeit keine Überraschungen gibt
calcdatum=$(date -d "${jahr}-${mon}-${tag} 12:00" '+%s')
# Beginnt die Ausstrahlung vor 0:00 Uhr und endet nach 0:00 Uhr,
# dann muss der Tag um 1 vorgestellt werden
if [ $(date -d "$ezeit" +%s) -lt $(date -d "$azeit" +%s) ]; then
calcdatum=$(($calcdatum + 86400))
fi
# Rückübertragung ins ISO-Format und anhängen an die Liste
termin=$(date -d "@$calcdatum" '+%Y-%m-%d')
echo "$termin $ezeit;$1;" >> $dn.ugf && echo 'Bestätigt.'; echo
|
2. Hauptskript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | #!/bin/bash
# Dem Skript muss genau ein Parameter mitgegeben werden, Prüfung
if [ $# -ne 1 ]; then
echo; echo "Verwendung: $0 '(StaffelxEpisode);Name des Titels'"; echo
exit
fi
# Subskript wird gesourced
source sub_1_3_serienpflege.sh
# Abbruch, wenn Eingabe im Subskript ungültig ist
if [ "$dn" = 'Eingabe ungültig.' ]; then
echo $dn; echo; exit
fi
# Ausstieg, wenn die Bedienung des Skripts sachlich falsch ist
if ! fgrep -q "$1" $dn.ugf 2> /dev/null; then
echo 'Diese Folge wurde nicht als ungesehen eingetragen. Falsche Auswahl?'; echo
else # Gesehene Folge wird aus der Liste der ungesehenen Folgen gelöscht
sed -i "/$1/d" $dn.ugf && echo 'Bestätigt.'; echo
fi
|
Subskript:
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 | #!/bin/bash
# Abfrage, welche Serie bearbeitet werden soll
# Auflistung mit Kurztitel der jeweiligen Serie
echo "Welche Serie?"
echo -e "\t1 = Detektiv Conan | 2 = Inuyasha | 3 = Konosuba | 4 = One Punch Man"
read -p "=> " ser
# Zuweisung der Variablen
case $ser in
1) dn='Detektiv_Conan' # Dateiname, nicht zwingend identisch mit Kurztitel
luecke='' # nur bei Bedarf
;;
2) dn='Inuyasha' > dn
luecke='Banryuu gegen die Windnarbe' # Hier hat die Liste noch eine Lücke
;;
3) dn='Konosuba' > dn
luecke=''
;;
4) dn='One_Punch_Man' > dn
luecke=''
;;
*) dn='Eingabe ungültig.' # Abweichung, um Falscheingabe abzufangen
luecke=''
;;
esac
|
Wegen der Redundanzen in Zeile 34-37 des 1. Hauptskripts muss ich mir noch etwas einfallen lassen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12821
|
wxpte schrieb:
Wegen der Redundanzen in Zeile 34-37 des 1. Hauptskripts muss ich mir noch etwas einfallen lassen.
Eine einfache Variante: | selected="$(fgrep -m1 "$1" $dn.txt)"
tag=$(echo "$selected" | cut -d\; -f3 | cut -d\. -f1)
...
|
|
wxpte
(Themenstarter)
Anmeldungsdatum: 20. Januar 2007
Beiträge: 1175
Wohnort: Schäl Sick
|
Ursprünglich hatte ich etwas mit Arrays im Sinn, aber dieser Weg gefällt mir sogar noch besser. So sieht das jetzt aus:
| ugfolge=$(fgrep -m1 "$1" $dn.txt); sdatum=$(cut -d\; -f3 <<<"$ugfolge") # Suchergebnis + Datum
tag=$(cut -d\. -f1 <<<"$sdatum"); mon=$(cut -d\. -f2 <<<"$sdatum")
szeit=$(cut -d\; -f4,5 <<<"$ugfolge" | sed 's/ Uhr//g' | sed 's/\./:/g') # Umwandlung der Zeiten ins date-Format
azeit=$(cut -d\; -f1 <<<"$szeit"); ezeit=$(cut -d\; -f2 <<<"$szeit")
|
Nochmals danke. 👍
|