0

Following the original issue described here:- Rip chapters of a DVD to separate files

..would someone help us understand what the following code is doing:-

# 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]}

We'd like to do the same thing and have tried to use the code. Unfortunately it doesn't work for us and because our understanding is limited we are unable to debug it.

We understand the basic idea of using sed but can't understand how it is managing to:-

  1. Resolve any pattern to in order to substitute.
  2. Produce any pattern to substitue with.

Also, its coupling here with eval() is beyond us. Plus there are three uses of # that we just don't get either.

Please help. Thanks.

xanda
  • 1

1 Answers1

2

First of all, since you didn't mention it, I'm assuming this is a bash script.

The high-level gloss of these two lines are that they extract the title number and chapter number from the output of lsdvd and store them in an array called cells.

The code given likely doesn't work because to_cell=${cell[title_num]} in the last line should be to_cell=${cells[title_num]}.

Here is a more detailed breakdown:

The sed command searches for the numbers following Title: and Chapters: in the output from lsdvd. sed then stores those numbers in \1 and \2 respectively. sed outputs a string of the form cells[$((10#\1))]=$((10#\2)), replacing the backslash references with the title and chapter numbers.

I believe you are confused as well by the $((10#x)) syntax. Here is the breakdown: $((expression)) in bash means "treat expression as an arithmetic expression and evaluate it" while y#x is an arithmetic expression meaning "treat x as a base y number and convert it to decimal." So for instance 2#10 evaluates to 2 (since 10 represents 2 in base 2), 10#10 evaluates to 10 (since converting a base 10 number to decimal doesn't do anything) and 3#4 throws an error (since "4" is not a legal symbol in base 3). More info is available from the ARITHMETIC EVALUATION section of man bash.

So the sed command just outputs a string that looks like this: cells[$((10#x))]=$((10#y)) where x and y are numbers. That gets passed to eval. I think you know enough at this point to realize that evaluating this string just results in standard array assignment in bash, since after evaluating the arithmetic expressions, the string looks like cells[x]=y.

The last line is just some additional variable assignment, with one trick. ${#cells[@]} just evaluates to the number of items in the cells array.

That's the gist of it.

jayhendren
  • 8,384
  • 2
  • 33
  • 58