Usando eval e sed para realizar contagem e controle de script

Usando eval e sed para realizar contagem e controle de script

Seguindo o problema original descrito aqui: - Copie capítulos de um DVD para arquivos separados

..alguém poderia nos ajudar 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#\1))]=$((10#\2));/p')
titles=${#cells[@]} title_num=2 from_cell=1 to_cell=${cell[title_num]}

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

Compreendemos a ideia básica de usar o sed, mas não conseguimos entender como ele consegue: -

  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, existem três usos de # que também não entendemos.

Por favor ajude. Obrigado.

Responder1

Em primeiro lugar, como você não mencionou isso, presumo que seja 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 lsdvde os armazenam em uma matriz chamada cells.

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

Aqui está uma análise mais detalhada:

O sedcomando procura os números seguintes Title:e Chapters:na saída de lsdvd. sedem seguida, armazena esses números em \1e \2respectivamente. sedgera uma string no formato cells[$((10#\1))]=$((10#\2)), substituindo as referências de barra invertida pelo título e pelos números dos capítulos.

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

Portanto, o sedcomando apenas gera uma string parecida com esta: cells[$((10#x))]=$((10#y))onde xe ysão números. Isso é passado para eval. Acho que você já sabe o suficiente para perceber que avaliar essa string apenas resulta na atribuição de array 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 adicional de variáveis, com um truque. ${#cells[@]}apenas avalia o número de itens na cellsmatriz.

Essa é a essência da questão.

informação relacionada