Nach dem hier beschriebenen ursprünglichen Problem: - Rippen Sie Kapitel einer DVD in separate Dateien
..kann uns jemand helfen zu verstehen, was der folgende Code macht:-
# count Titles, and count Cells per title.
# eg. ${cell[1]} is the Count of Cells for the first title
# ${cell[titles]} is the Count of Cells for the last title
eval $(lsdvd | sed -n 's/Title: \([0-9]\+\), .* Chapters: \([0-9]\+\), Cells: .*/cells[$((10#\1))]=$((10#\2));/p')
titles=${#cells[@]} title_num=2 from_cell=1 to_cell=${cell[title_num]}
Wir möchten das Gleiche tun und haben versucht, den Code zu verwenden. Leider funktioniert er bei uns nicht und da unser Verständnis begrenzt ist, können wir ihn nicht debuggen.
Wir verstehen die Grundidee der Verwendung von sed, können aber nicht nachvollziehen, wie es Folgendes erreicht:
- Lösen Sie jedes beliebige Muster auf, um es zu ersetzen.
- Erstellen Sie ein beliebiges Muster zum Ersetzen.
Auch die Kopplung mit eval() ist uns ein Rätsel. Außerdem gibt es drei Verwendungsmöglichkeiten von #, die wir einfach nicht verstehen.
Bitte helfen Sie. Danke.
Antwort1
Da Sie es nicht erwähnt haben, gehe ich zunächst davon aus, dass es sich um ein Bash-Skript handelt.
Die allgemeine Bedeutung dieser beiden Zeilen besteht darin, dass sie die Titelnummer und die Kapitelnummer aus der Ausgabe von extrahieren lsdvd
und in einem Array namens speichern cells
.
Der angegebene Code funktioniert wahrscheinlich nicht, da to_cell=${cell[title_num]}
in der letzten Zeile stehen sollte to_cell=${cells[title_num]}
.
Hier ist eine detailliertere Aufschlüsselung:
Der Befehl sucht in der Ausgabe von nach sed
den auf Title:
und folgenden Zahlen . Anschließend speichert er diese Zahlen in bzw .. gibt eine Zeichenfolge in der Form aus und ersetzt dabei die Backslash-Referenzen durch die Titel- und Kapitelnummern.Chapters:
lsdvd
sed
\1
\2
sed
cells[$((10#\1))]=$((10#\2))
Ich glaube, Sie sind auch von der $((10#x))
Syntax verwirrt. Hier ist die Aufschlüsselung: $((expression))
bedeutet in Bash „ expression
als arithmetischen Ausdruck behandeln und auswerten“, während y#x
ein arithmetischer Ausdruck bedeutet „ x
als Basiszahl behandeln y
und in Dezimalzahl umwandeln“. So wird beispielsweise 2#10
ausgewertet zu 2
(da 10 2 in Basis 2 darstellt), 10#10
wird ausgewertet zu 10
(da die Umwandlung einer Basis 10-Zahl in Dezimalzahl nichts bewirkt) und 3#4
gibt einen Fehler aus (da „4“ in Basis 3 kein gültiges Symbol ist). Weitere Informationen finden Sie im ARITHMETIC EVALUATION
Abschnitt von man bash
.
Der sed
Befehl gibt also einfach einen String aus, der wie folgt aussieht: cells[$((10#x))]=$((10#y))
wobei x
und y
Zahlen sind. Dieser wird an übergeben eval
. Ich denke, Sie wissen an diesem Punkt genug, um zu erkennen, dass die Auswertung dieses Strings einfach zu einer Standard-Array-Zuweisung in Bash führt, da der String nach der Auswertung der arithmetischen Ausdrücke wie folgt aussieht cells[x]=y
.
Die letzte Zeile ist lediglich eine zusätzliche Variablenzuweisung mit einem Trick. Sie ${#cells[@]}
wird einfach als Anzahl der Elemente im cells
Array ausgewertet.
Das ist der Kern der Sache.