Eu tenho um youtube-dl
comando que, quando executado, gera duas novas linhas e estou tentando capturar cada uma delas para variáveis.
Aqui está o que tenho até agora, mas por algum motivo não consigo entender, ele apenas captura a primeira linha de saída enquanto descarta a segunda ( $audio
está vazia).
read -r video audio <<< "$(youtube-dl -g --youtube-skip-dash-manifest https://www.youtube.com/watch?v=-gcvAxJJiGo)"
Como posso corrigi-lo para capturar as duas entradas ou, alternativamente, existe uma maneira mais confiável de fazer isso?
read
lê uma linha por design . A maneira mais simples de ler duas linhas é usarread
duas vezes.read -u
não é portátil, nem é<(…)
. Eles funcionam no Bash e sua pergunta é marcada como bash , então eles devem funcionar para você.Observe que coloquei entre aspas simples a string que contém
?
caso você tenha um diretóriohttps:/www.youtube.com/
e um arquivo correspondente nele. É apenas remotamente possível, ainda citar caracteres curinga que não devem ser tratados como curingas é uma boa prática em qualquer shell. Compare o que acontece em Zsh .Vazio
IFS
é a coisa certa em geral , quando você quer ler uma linha.Esta outra resposta não usa
exec
e é boa. É minha preferência pessoal configurar a entrada visualmente antes das ferramentas que a usarão (compare esta resposta ). Infelizmente<(…) { …; }
não funciona. Comexec
eu consigo.Ou posso fazer isso canalizando
youtube-dl
para o resto do script.Normalmente, o Bash executa o
{ … }
fragmento em um subshell, portanto, as variáveis não sobreviverão após o}
.shopt -s lastpipe
pode alterar isso (se o controle de trabalho não estiver ativo). Semlastpipe
(o que não é portátil) toda a abordagem é portátil, mas você precisa executar tudo que usa as variáveis dentro do{ }
bloco porque você não sabe se é um subshell ou não (POSIX permite os dois comportamentos). Observe que o stdin dentro do bloco vem deyoutube-dl
; se alguma coisa dentro do bloco precisar usar o stdin de todo o script, talvez você precise usarexec
de qualquer maneira para fazer malabarismos com os descritores.Outra abordagem portátil é assim:
Em vez de
head
etail
você pode usarsed
ouawk
para isolar a linha certa.Observe que esta solução não usa arquivos
read
. Se você precisa de recursosread
, então este não é o caminho. Parece que você não precisa dos recursosread
neste caso específico.Mesmo que
youtube-dl
fosse muito rápido, eu não aconselhariavideo="$(youtube-dl … | head -n 1)"
maisaudio="$(youtube-dl … | …)"
. Sevideo
eaudio
vêm do mesmoinput
, da mesma invocação deyoutube-dl
, então eles são tão coerentes quanto a ferramenta permite. Caso contrário, podem ser incoerentes. Francamente, não sei quão incoerentes podem ser (se alguma vez); mas eu sei que em geral é melhor consultar uma vez (por exemplodate +%H:+%M
, deve sempre ser coerente;date +%H; date +%M
vai surpreendê-lo se você executá-lo pouco antes de uma hora).read -r video audio
irá capturar a primeira palavra ($IFS separada) em "vídeo" e o resto da linha em "áudio"Outra maneira de capturar 2 linhas é com agrupamento de comandos e uma substituição de processo:
O espaço entre
< <(
é importante: a<(process substitution)
age como um arquivo, então você está usando<
para redirecionar a entrada de um arquivo.Acabou de me ocorrer: outra maneira de ler as linhas de saída é o
mapfile
comando: