Verwenden von eval und sed zum Zählen und zur Skriptsteuerung

Verwenden von eval und sed zum Zählen und zur Skriptsteuerung

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:

  1. Lösen Sie jedes beliebige Muster auf, um es zu ersetzen.
  2. 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 lsdvdund 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 sedden 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:lsdvdsed\1\2sedcells[$((10#\1))]=$((10#\2))

Ich glaube, Sie sind auch von der $((10#x))Syntax verwirrt. Hier ist die Aufschlüsselung: $((expression))bedeutet in Bash „ expressionals arithmetischen Ausdruck behandeln und auswerten“, während y#xein arithmetischer Ausdruck bedeutet „ xals Basiszahl behandeln yund in Dezimalzahl umwandeln“. So wird beispielsweise 2#10ausgewertet zu 2(da 10 2 in Basis 2 darstellt), 10#10wird ausgewertet zu 10(da die Umwandlung einer Basis 10-Zahl in Dezimalzahl nichts bewirkt) und 3#4gibt einen Fehler aus (da „4“ in Basis 3 kein gültiges Symbol ist). Weitere Informationen finden Sie im ARITHMETIC EVALUATIONAbschnitt von man bash.

Der sedBefehl gibt also einfach einen String aus, der wie folgt aussieht: cells[$((10#x))]=$((10#y))wobei xund yZahlen 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 cellsArray ausgewertet.

Das ist der Kern der Sache.

verwandte Informationen