Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

[gelöst] bash-Script mit Doppelschleife

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

Christina hat geschrieben: 22. Sep 2020, 22:57 .. statt "$1" noch "$((i+1))" eingefügt ..hoffe, das ist im bash-Script so richtig.
absolut richtig

Christina hat geschrieben: 22. Sep 2020, 22:57

Code: Alles auswählen

#!/bin/bash

echo -e "FLAC-Zielverzeichnis: \c"
read destin_path
source_path="."
IFS=$'\n'

fa=($(find $source_path -maxdepth 1 -type f -name "*.flac" -printf "%f\n" | sort -f))
fb=($(find $destin_path -maxdepth 1 -type f -name "*.flac" -printf "%p\n" | sort -f))
len_a=${#fa[@]}
len_b=${#fb[@]}
if [[ $len_a -eq $len_b ]]; then
  for ((i=0; i<${len_a}; i++)); do
    printf "%.2d: %s -> %s\n" "$((i+1))" "${fa[i]}" "${fb[i]}"
    metaflac --export-tags-to=- ${fa[i]} | metaflac --remove-all-tags --import-tags-from=- ${fb[i]}
  done
else
  printf "Anzahl Dateien unterschiedlich: Quellverzeichnis %d <-> Zielverzeichnis %d.\n" "$len_a" "$len_b"
fi
exit 0
Wenn jetzt kein Fehler mehr drin ist ...
Einges wäre noch verbesserungswürdig, aber
dein script erfüllt die Aufgabe, es ist für Dritte leicht verständlich und es entspricht dem neuesten Stand von Bash.
Von mir bekommst du ein Befriedigend.

Gruß
Gräfin Klara
abgdf
Guru
Guru
Beiträge: 3320
Registriert: 13. Apr 2004, 21:15

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von abgdf »

Tja ...

Das löst aber nicht die Probleme mit der verd****** bash.

Beispiel: Bereitet ein Verzeichnis namens "test" mit folgendem Skript vor:

Code: Alles auswählen

#!/bin/bash
mkdir test
touch "./test/test1"
touch "./test/test2"
touch "./test/hallo welt"
Und dann laßt dieses Skript laufen, das dem von Christina nachempfunden ist:

Code: Alles auswählen

#!/bin/bash

fa=($(find "./test" -maxdepth 1 -type f -name "*" -printf "%f\n"))
len_fa=${#fa[@]}

echo $len_fa

for ((i=0; i<${len_fa}; i++)); do
    echo "$i    ${fa[i]}"
done
Ihr erhaltet folgende Ausgabe:

Code: Alles auswählen

4
0    test1
1    test2
2    hallo
3    welt
Und das ist mal wieder nicht das Ergebnis, das man haben will. Sondern man würde Folgendes wollen (und nicht bekommen):

Code: Alles auswählen

3
0    test1
1    test2
2    hallo welt
------

In Perl dagegen mal wieder kein Problem:

Code: Alles auswählen

#!/usr/bin/perl
use warnings;
use strict;

my @fa = <./test/*>;

print $#fa + 1 . "\n";
for (my $i = 0; $i <= $#fa; $i++) {
    print "$i    $fa[$i]\n";
}
Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

abgdf hat geschrieben: 23. Sep 2020, 14:54 Tja ...

Das löst aber nicht die Probleme mit der verd****** bash.
Und das ist mal wieder nicht das Ergebnis, das man haben will...
Weil du
IFS=$'\n'
vergessen hast
abgdf hat geschrieben: 23. Sep 2020, 14:54 In Perl dagegen mal wieder kein Problem:
Absoluter overkill für eine so simple Aufgabe
abgdf
Guru
Guru
Beiträge: 3320
Registriert: 13. Apr 2004, 21:15

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von abgdf »

Gräfin Klara hat geschrieben: 23. Sep 2020, 15:42 Weil du
IFS=$'\n'
vergessen hast
Ach so. Wieder was gelernt. :thumbs:
abgdf hat geschrieben: 23. Sep 2020, 14:54Absoluter overkill für eine so simple Aufgabe
Das schrieb robi auch schonmal: "Benutze kein Perl, viel zu groß".
Aber wozu? Mein Rechner ist (schon wieder) alt, und trotzdem macht es ihm überhaupt nichts aus. Wenn ich dagegen "awk" zur Datenverarbeitung bemühe, das kleiner ist (wie robi das tut), macht es mir eine Menge aus. Dauert einfach viel länger, wenn man's nicht gewohnt ist.
Insofern bin ich der Meinung: Wir haben heute die Ressourcen, und es ist kein Problem, sie auch einzusetzen. Die 80er waren gut, aber manche Probleme von damals haben wir glücklicherweise nicht mehr. Mangelnde Speicherkapazität und Prozessor-Leistung gehören dazu.
Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

abgdf hat geschrieben: 23. Sep 2020, 16:50 ..
Insofern bin ich der Meinung: Wir haben heute die Ressourcen, und es ist kein Problem, sie auch einzusetzen.
Für diesen sanften Hügel nehme ich die Sandalen mit Grip,
du bevorzugst die schweren Bergstiefel mit Stahleinlagen.
Hinauf kommen wir beide,
Benutzeravatar
Geier0815
Administrator
Administrator
Beiträge: 4385
Registriert: 14. Jun 2004, 09:12

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von Geier0815 »

Das Entscheidende ist doch das jeder das nehmen kann womit er, und gegebenenfalls sein Umfeld, am Besten zurecht kommt oder was im am besten gefällt.
Wenn Windows die Lösung ist...
kann ich dann bitte das Problem zurück haben?
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3180
Registriert: 25. Aug 2004, 02:13

Re: bash-Script mit Doppelschleife

Beitrag von robi »

Christina hat geschrieben: 21. Sep 2020, 20:40 Wie schreibt man eigentlich in der bash die if-Anweisung korrekt? Mit doppelter eckiger Klammer [[…]] ?
Ich habe verschiedene Varianten im www gesehen.
Gräfin Klara hat geschrieben: 22. Sep 2020, 11:13 [ .. ] hat historische Gründe. Es läßt sich nicht ändern, nur erweitern, sonst würden Millionen alte scripts nicht mehr funktionieren.
[[ .. ]] ist neu, es bietet mehr und kann auch alles was [ .. ] kann. Denk nicht darüber nach, verwende [[ .. ]]
Dies Aussage greift aber sehr kurz.

Das eine ist intern in der Bash verbaut "[[ ... ]]"
man bash hat geschrieben:[[ expression ]]
Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below under
CONDITIONAL EXPRESSIONS. Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable
expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as -f must be unquoted
to be recognized as primaries.
....
Das andere "[ ....... " ist nichts weiter als ein Hardlink (bzw heute oft eine anderes kompilierte Form) von /usr/bin/test

Code: Alles auswählen

robi@linux001 >which [
/usr/bin/[
robi@linux001 >ls -il /usr/bin/[
1053488 -rwxr-xr-x 1 root root 39704 17. Mär 2014  /usr/bin/[
robi@linux001 >ls -il /usr/bin/test
1055508 -rwxr-xr-x 1 root root 35616 17. Mär 2014  /usr/bin/test 
Nachweisen kann man das zum Beispiel wenn man mal in den Binärcode reinschaut, hier mal als Beispiel ein Bereich wo die HELP Infomationen von beiden Binärdateien gegenüberstellt.

Code: Alles auswählen

robi@linux001 >strings /usr/bin/[  | grep FILE
  FILE1 -ef FILE2   FILE1 and FILE2 have the same device and inode numbers
  FILE1 -nt FILE2   FILE1 is newer (modification date) than FILE2
  FILE1 -ot FILE2   FILE1 is older than FILE2
  -b FILE     FILE exists and is block special
  -c FILE     FILE exists and is character special
  -d FILE     FILE exists and is a directory
  -e FILE     FILE exists
  -f FILE     FILE exists and is a regular file
  -g FILE     FILE exists and is set-group-ID
  -G FILE     FILE exists and is owned by the effective group ID
  -h FILE     FILE exists and is a symbolic link (same as -L)
  -k FILE     FILE exists and has its sticky bit set
  -L FILE     FILE exists and is a symbolic link (same as -h)
  -O FILE     FILE exists and is owned by the effective user ID
  -p FILE     FILE exists and is a named pipe
  -r FILE     FILE exists and read permission is granted
  -s FILE     FILE exists and has a size greater than zero
  -S FILE     FILE exists and is a socket
  -u FILE     FILE exists and its set-user-ID bit is set
  -w FILE     FILE exists and write permission is granted
  -x FILE     FILE exists and execute (or search) permission is granted
Except for -h and -L, all FILE-related tests dereference symbolic links.
robi@linux001 >strings /usr/bin/test  | grep FILE
  FILE1 -ef FILE2   FILE1 and FILE2 have the same device and inode numbers
  FILE1 -nt FILE2   FILE1 is newer (modification date) than FILE2
  FILE1 -ot FILE2   FILE1 is older than FILE2
  -b FILE     FILE exists and is block special
  -c FILE     FILE exists and is character special
  -d FILE     FILE exists and is a directory
  -e FILE     FILE exists
  -f FILE     FILE exists and is a regular file
  -g FILE     FILE exists and is set-group-ID
  -G FILE     FILE exists and is owned by the effective group ID
  -h FILE     FILE exists and is a symbolic link (same as -L)
  -k FILE     FILE exists and has its sticky bit set
  -L FILE     FILE exists and is a symbolic link (same as -h)
  -O FILE     FILE exists and is owned by the effective user ID
  -p FILE     FILE exists and is a named pipe
  -r FILE     FILE exists and read permission is granted
  -s FILE     FILE exists and has a size greater than zero
  -S FILE     FILE exists and is a socket
  -u FILE     FILE exists and its set-user-ID bit is set
  -w FILE     FILE exists and write permission is granted
  -x FILE     FILE exists and execute (or search) permission is granted
Except for -h and -L, all FILE-related tests dereference symbolic links.
Damit ist beides etwas komplett anderes, das eine ist intern in der Bash verbaut und wird sofort ohne Umwege genutzt, (und kann wenn ich eine andere Shell als die Bash verwende anders funktionieren) und das andere ist ein eigenes Programm dazu muss erst ein neuer Prozess mittels forc erstellt werden, dann der Binärcode der Datei in den neuen Prozess geladen werden und dann der neue Prozess dort gestartet werdeb. Das ist genau so als wenn Subprozesse erstellt werden wie für jedes andere im Scriptcode verwendete (Basch)externe Tool auch. zB grep, sed, cat , find ..... .
Und kostet damit Zeit und Ressourcen und macht zB in großen Schleifen die Abarbeitung von Scripts langsam.

Auch die möglichen Optionen/Operatoren und Möglichkeiten sind recht verschieden.
Damit sollte man sich schon bewusst sein, das das [[ ]] und [ ] nicht wirklich das Gleiche oder nur Historisch-und-Nachfolger ist.

IF ist nun auch nicht unbedingt nur für [, [[ oder test bestimmt. In der Manpage von bash findet man die Definition.
[quote="man bash"
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit status is zero,
the corresponding then list is executed and the command completes. Otherwise, the else list is executed, if present. The exit status is the exit status of the
last command executed, or zero if no condition tested true.
ich kann also hier eine Abfrage (if) auf das (End)Ergebniss einer ganzen Latte von Befehlen machen, Wenn der letzte Befehl in der Liste den Status 0 zurückgibt dann wird die Befehlsliste hinter then ausgeführt, sonst hinter else

Code: Alles auswählen

robi@linux001 >if ls ; ls -l ; ls -il | grep "File4" ; then echo vorhanden ; else echo nicht vorhanden ; fi
File1  File2  File3  File4  File5  File6
insgesamt 0
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File1
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File2
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File3
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File4
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File5
-rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File6
3021659 -rw-rw-r-- 1 puppe users 0 25. Sep 14:26 File4
vorhanden
hier wird als "TEST" zuerst "ls" ausgeführt, anschließend "ls -l" und anschließend "ls -il | grep File4"
Ausgewertet wird der Rückgabewert von grep und da grep was gefunden hat wird der then-Zweig durchlaufen, in dem natürlich dann auch wieder jede Menge Befehle in einer Liste stehen könnten.

Von da her ist if-then-else-fi in der Bash etwas mächtiger als in vielen Programmiersprachen, und man kann damit durchaus Programmabläufe programmieren, wo man sich extrem schwer tut dieses in eine andere Programmiersprache eins-zu-eins zu übersetzen. Allerdings werden hier die Möglichkeiten der Bash meist an dieser Stelle gar nicht richtig ausgenutzt, weil natürlich jeder "Programmierer" irgendwie hier in allgemein gültigen logischen Algorithmen denkt und damit selten die Möglichkeiten und Stärken von einzelnen Programmiersprachen aus Grundlage für die Optimierung eines Programmablauf zugrundelegt.

robi
josef-wien
Ultimate Guru
Ultimate Guru
Beiträge: 5461
Registriert: 23. Sep 2008, 17:09

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von josef-wien »

robi hat geschrieben:Das andere "[ ....... " ist nichts weiter als ein Hardlink (bzw heute oft eine anderes kompilierte Form) von /usr/bin/test
Da muß ich mich doch glatt selbst zitieren: https://linux-club.de/forum/viewtopic.p ... 14#p792514
Und dann noch den Anfang des Abschnitts "CONDITIONAL EXPRESSIONS" schreiben:
man bash hat geschrieben:Conditional expressions are used by the [[ compound command and the test and [ builtin commands to test file attributes and perform string and arithmetic comparisons.
/usr/bin/[ und /usr/bin/test sind - wie von Dir erwähnt - normale Programme.
Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

robi hat geschrieben: 25. Sep 2020, 15:40
Gräfin Klara hat geschrieben: 22. Sep 2020, 11:13 [ .. ] hat historische Gründe. Es läßt sich nicht ändern, nur erweitern, sonst würden Millionen alte scripts nicht mehr funktionieren.
[[ .. ]] ist neu, es bietet mehr und kann auch alles was [ .. ] kann. Denk nicht darüber nach, verwende [[ .. ]]
Dies Aussage greift aber sehr kurz.
Die Erklärung zu [ -> test ist unter Bash Archäologie.
Interessant? Ja! wertvoll? Nein!
robi hat geschrieben: 25. Sep 2020, 15:40 Auch die möglichen Optionen/Operatoren und Möglichkeiten sind recht verschieden.
Damit sollte man sich schon bewusst sein, das das [[ ]] und [ ] nicht wirklich das Gleiche oder nur Historisch-und-Nachfolger ist.
Natürlich verschieden, das erfordert aber nicht die Kenntnis beider Regeln.
Gräfin Klara hat geschrieben: 22. Sep 2020, 11:13 [[ .. ]] ist neu, es bietet mehr und kann auch alles was [ .. ] kann. Denk nicht darüber nach, verwende [[ .. ]]
Dabei bleibe ich

Gruß
Gräfin Klara
Christina
Member
Member
Beiträge: 61
Registriert: 4. Mär 2019, 13:44

Re: bash-Script mit Doppelschleife

Beitrag von Christina »

Gräfin Klara hat geschrieben: 26. Sep 2020, 11:51Die Erklärung zu [ -> test ist unter Bash Archäologie.
Interessant? Ja! wertvoll? Nein!
Und mehr als [[ … ]] verwirrt mich im Moment nur.

Ich habe noch eine Frage zu ls & find im bash-Script:
Um die getaggten Flac-Dateien anschließend umzubenennen, genügt ja einfach nach der Zeile mit metaflac:

Code: Alles auswählen

mv ${fb[i]} "$destin_path/${fa[i]}"
Unschön aber aber ohne Fehler ist der doppelte Schrägstrich im String,
wenn ich bei $destin_path bereits einen abschließenden Schrägstrich habe.

Jetzt überlege ich, wie ich immer nur einen Schrägstrich hinten am Verzeichnis bekommen kann.

Code: Alles auswählen

ls -dF /home/christina/Tascam/Dolly Parton/
/home/christina/Tascam/Dolly Parton//
So geht es also nicht.
Mit welchem Kommando kann man das //-Problem am Pfadende korrekt lösen (auch wenn es trotzdem funktioniert)?

Ganz radikal und einfach wäre, wenn ich die fertigen Dateien ins Quellverzeichnis verschiebe, aber das möchte ich nicht.

Code: Alles auswählen

mv -f ${fb[i]} ${fa[i]}
Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

Oben steht:

Code: Alles auswählen

read destin_path
Kann bzw. sollte sein:

Code: Alles auswählen

read -r
destin_path="${REPLY%/}"
if [[ ! -d "$destin_path" ]]; then
  printf "Pfad %s existiert nicht\n" "$destin_path"
  exit 1
fi
...
REPLY ist eine interne Variable für read.
destin_path="${REPLY%/}" extrahiert aus dem string $REPLY alles nach destin_path, außer ein eventuell folgendes /
abgdf
Guru
Guru
Beiträge: 3320
Registriert: 13. Apr 2004, 21:15

Re: bash-Script mit Doppelschleife

Beitrag von abgdf »

Christina hat geschrieben: 26. Sep 2020, 13:32Jetzt überlege ich, wie ich immer nur einen Schrägstrich hinten am Verzeichnis bekommen kann.

Code: Alles auswählen

ls -dF /home/christina/Tascam/Dolly Parton/
/home/christina/Tascam/Dolly Parton//
So geht es also nicht.
Indem Du in dem ls-Befehl das "-F" wegläßt?

Schrägstriche sind normalerweise nicht Teil des Verzeichnisnamens.
josef-wien hat geschrieben:/usr/bin/[ und ... sind - wie von Dir erwähnt - normale Programme.
Cool, wußte ich auch nicht. :thumbs:

Offenbar nennen einige ihre Programme "[" und ihre Verzeichnisse "v//". :D
Christina
Member
Member
Beiträge: 61
Registriert: 4. Mär 2019, 13:44

Re: bash-Script mit Doppelschleife

Beitrag von Christina »

abgdf hat geschrieben: 26. Sep 2020, 16:35 Indem Du in dem ls-Befehl das "-F" wegläßt?
Das klappt dann auch nicht im bash-Script:

Code: Alles auswählen

ls -d /home/christina/Tascam/Dolly\ Parton
/home/christina/Tascam/Dolly Parton
-> Gar kein abschließendes /.
 
Gräfin Klara hat geschrieben: 26. Sep 2020, 15:39 destin_path="${REPLY%/}" extrahiert aus dem string $REPLY alles nach destin_path, außer ein eventuell folgendes /
Das meine ich. :-)
Die Lösung musste ja sehr einfach sein. Das wird überall benötigt, wo Pfadangaben in Shellskripten benutzt werden.
Und destin_path="${REPLY#/}" entfernt einen eventuellen führenden /, habe ich eben gelesen:
Quora.com: What does the percent symbol mean on Bash?
Den Exit-Code habe ich jetzt auch beim Vergleich der Anzahl der Flac-Dateien drin. Dann kann ich das per echo $? abfragen.

Code: Alles auswählen

#!/bin/bash

echo -e "FLAC-Zielverzeichnis: \c"
read -r
source_path="."
destin_path="${REPLY%/}"
if [[ ! -d "$destin_path" ]]; then
    printf "Pfad \"%s\" existiert nicht.\n" "$destin_path"
    exit 1
fi

IFS=$'\n'
fa=($(find $source_path -maxdepth 1 -type f -name "*.flac" -printf "%f\n" | sort -f))
fb=($(find $destin_path -maxdepth 1 -type f -name "*.flac" -printf "%p\n" | sort -f))
len_a=${#fa[@]}
len_b=${#fb[@]}
if [[ $len_a -ne $len_b ]]; then
    printf "Anzahl Dateien unterschiedlich: Quellverzeichnis %d <-> Zielverzeichnis %d.\n" "$len_a" "$len_b"
    exit 1
fi

for ((i=0; i<${len_a}; i++)); do
    printf "%.2d: %s -> %s\n" "$((i+1))" "${fa[i]}" "${fb[i]}"
    metaflac --export-tags-to=- ${fa[i]} | metaflac --remove-all-tags --import-tags-from=- ${fb[i]}
    mv ${fb[i]} "$destin_path/${fa[i]}"
done
exit 0
Die Stringverkettung per " $…/$… " ganz unten beim mv passt auch so, oder? Das ist kein historischer Code?
In C würde ich spontan sprintf nehmen.
abgdf
Guru
Guru
Beiträge: 3320
Registriert: 13. Apr 2004, 21:15

Re: [gelöst] bash-Script mit Doppelschleife

Beitrag von abgdf »

Schrägstich gehört nicht zum Verzeichnisnamen.

Code: Alles auswählen

mkdir "test/"
ls -d test/
ls -d test
Ausgabe:

Code: Alles auswählen

test/
test
Christina
Member
Member
Beiträge: 61
Registriert: 4. Mär 2019, 13:44

Re: bash-Script mit Doppelschleife

Beitrag von Christina »

Der abschließende / kennzeichnet ein Verzeichnis. Das habe ich als Anfängerin so gelesen und mir das gleich angewöhnt.
Manche Programme verlangen den trailing '/' bei Pfadangaben sogar. Das steht dann auch im manual page.
Gräfin Klara
Hacker
Hacker
Beiträge: 567
Registriert: 23. Jun 2008, 20:51

Re: bash-Script mit Doppelschleife

Beitrag von Gräfin Klara »

Christina hat geschrieben: 26. Sep 2020, 21:35 ..
Den Exit-Code habe ich jetzt auch beim Vergleich der Anzahl der Flac-Dateien drin. Dann kann ich das per echo $? abfragen.
Perfekt!
Christina hat geschrieben: 26. Sep 2020, 21:35 Die Stringverkettung per " $…/$… " ganz unten beim mv passt auch so, oder? Das ist kein historischer Code?
Alles ok!
Christina hat geschrieben: 26. Sep 2020, 21:35 Der abschließende / kennzeichnet ein Verzeichnis. Das habe ich als Anfängerin so gelesen und mir das gleich angewöhnt.
Das solltest du dir abgewöhnen. @abgdf hat hier völlig Recht. Trailing / kennzeichnet nicht einen Verzeichnisnamen.
Sollte ein Programm das so verlangen, dann ist die Frage an den Programmierer "Was soll der Blödsinn" berechtigt.

Noch eine Kleinigkeit:

Code: Alles auswählen

for ((i=0; i<${len_a}; i++)); do
Diese Zeile erschwert die Arbeit des Interpreters enorm, die Variable ${len_a} so darzustellen, ist ein Bug.
Wie du oben bei ${REPLY%/} gesehen hast, kann man mit einem { (opening brace) eine spezielle Aufgabe anfordern.
Das kann sein Extrahieren, Löschen, Ändern, usw. von Inhalten in dieser Variable. Der Interpreter geht also nach
einem brace in seine Tiefen und sucht die geforderte Aufgabe. ${len_a} beinhaltet aber keine.
Diese unnötige Leistung muß der Interpreter bei jedem Durchlauf der loop erbringen. i < $len_a; wäre hier richtig.

Gruß
Gräfin Klara
Christina
Member
Member
Beiträge: 61
Registriert: 4. Mär 2019, 13:44

Re:bash-Script mit Doppelschleife

Beitrag von Christina »

Vielen Dank an euch für die Info!
Die for-Schleifenbedingung habe ich geändert. Ich hatte das letzten Mo. so von for i in ${!fa[@]}; do übernommen.
Jetzt habe ich eine schöne Scriptvorlage fürs nächste Mal!
Ein bash-Script hat wirklich Vorteile gegenüber C.
lg Christina
Wird in der bash bei der Variablendeklaration eigentlich nach Zeichen, Ganzzahl und Gleitkomma unterschieden?
abgdf
Guru
Guru
Beiträge: 3320
Registriert: 13. Apr 2004, 21:15

Re: Re:bash-Script mit Doppelschleife

Beitrag von abgdf »

Christina hat geschrieben: 27. Sep 2020, 15:41Wird in der bash bei der Variablendeklaration eigentlich nach Zeichen, Ganzzahl und Gleitkomma unterschieden?
Nicht (so streng) wie in C.
bash-Variablen können ja sowohl Strings als auch Zahlen speichern.
In Perl nennt man diese flexiblen Variablen "Skalarvariablen" oder "Skalare".
In dem wohl umfangreichsten Dokument zur bash, in dem man manchmal nachschlagen muß, dem "Advanced Bash-Scripting Guide", finde ich diesen Begriff nicht, aber in der Sache ist es eigentlich dasselbe:

https://tldp.org/LDP/abs/html/untyped.html
Christina hat geschrieben: 27. Sep 2020, 15:41Jetzt habe ich eine schöne Scriptvorlage fürs nächste Mal!
Ein bash-Script hat wirklich Vorteile gegenüber C.
bash ist gut für die Arbeit mit Dateien oder wenn man spezielle Kommandozeilenprogramme aufrufen will wie eben "metaflac".
Wenn man dagegen mehr Daten verarbeiten will (z.B. die Daten in Dateien), oder wenn man viel mit Strings und Listen arbeiten will, wäre Perl die bessere Wahl (natürlich gäbe es da auch eine "system()"-Funktion, um hier und da auch einen speziellen Shell-Befehl wie "metaflac" abzusetzen).
So ist es auch entstanden: Der Erfinder von Perl (Larry Wall) hatte viele Strings zu verarbeiten, und das war ihm in C (mit "strcpy()", usw.) zu umständlich. Deshalb mischte er einige Elemente aus der bash (und sed und awk) und C und formte daraus eine eigene (interpretierte) Programmiersprache (wobei er den Perl-Interpreter wiederum in C schrieb, er gab C also nicht völlig auf, im Gegenteil).
Also, wenn Du C kennst, und bash, dann würdest Du mit Perl sehr viel Spaß haben.
Es ist die eigentliche Sprache, die die Vorteile gegenüber C während der Programmierung hat. Die bash bezieht sich halt mehr auf die Arbeit mit Dateien.

Die meisten Linux-User lernen die Sprachen wohl in der Reihenfolge "erst bash, dann Perl, dann C" kennen.
Aber "erst C, dann bash, und dann ggf. Perl" ginge natürlich auch. ;)
Christina
Member
Member
Beiträge: 61
Registriert: 4. Mär 2019, 13:44

Re: bash-Script mit Doppelschleife

Beitrag von Christina »

Vielen Dank!
abgdf hat geschrieben: 27. Sep 2020, 16:46Die meisten Linux-User lernen die Sprachen wohl in der Reihenfolge "erst bash, dann Perl, dann C" kennen.
Aber "erst C, dann bash, und dann ggf. Perl" ginge natürlich auch. ;)
Bei mir zuerst C und ein paar Monate später Linux (leider nur Privatvergnügen). Ich lese auch hier einiges mit. openSUSE und als Tipp u.a. auch dieses Forum hier kenne ich durch einen Bekannten, zu dem ich aber keinen Kontakt mehr habe, seit er weggezogen ist.
Antworten