Usando eval e sed para realizar a contagem e controle de script

0

Após a edição original descrita aqui: Ripar capítulos de um DVD para separar arquivos

.. alguém nos ajudaria a entender o que o código a seguir está fazendo: -

# 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#))]=$((10#));/p')
titles=${#cells[@]} title_num=2 from_cell=1 to_cell=${cell[title_num]}

Gostaríamos de fazer o mesmo e tentamos usar o código. Infelizmente, isso não funciona para nós e, como nosso entendimento é limitado, não podemos depurá-lo.

Entendemos a ideia básica de usar o sed, mas não conseguimos entender como ele está conseguindo: -

  1. Resolva qualquer padrão para substituir.
  2. Produza qualquer padrão para substituir.

Além disso, seu acoplamento aqui com eval () está além de nós. Além disso, há três usos de # que simplesmente não conseguimos.

Por favor ajude. Obrigado.

    
por xanda 09.05.2014 / 17:17

1 resposta

2

Primeiro de tudo, desde que você não mencionou, estou assumindo que este é um script bash.

O brilho de alto nível dessas duas linhas é que elas extraem o número do título e o número do capítulo da saída de lsdvd e os armazenam em uma matriz chamada cells .

O código fornecido provavelmente não funciona porque to_cell=${cell[title_num]} na última linha deve ser to_cell=${cells[title_num]} .

Aqui está uma análise mais detalhada:

O comando sed procura os números que seguem Title: e Chapters: na saída de lsdvd . sed , em seguida, armazena esses números em e , respectivamente. sed exibe uma string no formato cells[$((10#))]=$((10#)) , substituindo as referências de barra invertida pelos números de título e capítulo.

Eu acredito que você esteja confuso também com a sintaxe $((10#x)) . Aqui está a divisão: $((expression)) in bash significa "tratar expression como expressão aritmética e avaliá-lo" enquanto y#x é uma expressão aritmética que significa "tratar x como base y number e convertê-lo em decimal " Portanto, por exemplo, 2#10 é avaliado como 2 (já que 10 representa 2 na base 2), 10#10 é avaliado como 10 (como converter um número base 10 em decimal não faz nada) e 3#4 gera um erro (já que "4" não é um símbolo legal na base 3). Mais informações estão disponíveis na seção ARITHMETIC EVALUATION de man bash .

Portanto, o comando sed exibe uma string parecida com esta: cells[$((10#x))]=$((10#y)) onde x e y são números. Isso é passado para eval . Eu acho que você sabe o suficiente neste momento para perceber que avaliar esta string apenas resulta na atribuição de matriz padrão no bash, já que depois de avaliar as expressões aritméticas, a string se parece com cells[x]=y .

A última linha é apenas uma atribuição de variável adicional, com um truque. ${#cells[@]} apenas avalia o número de itens na matriz cells .

Essa é a essência disso.

    
por 09.05.2014 / 18:52

Tags