Difference: TWikiBarTalk008 (1 vs. 17)

Revision 1725 Dec 2017 - Main.PauloSantana

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII

Line: 480 to 480
       - Waiter, send two, mine is low foam ...
Changed:
<
<
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me. .
>
>
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me. .
  Thanks!
Added:
>
>
next

-- PauloSantana - 25 Dec 2017

Revision 1618 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII

Added:
>
>
 


Line: 4 to 5
 


Added:
>
>
This is a very new translation from Portuguese to English. Please contribute to the development of this site indicating errors and and/or suggesting corrections and materials for this person.
      - Hello dude! Is everything okay??

     - Cool! I wanted to show you what I did but I know you will want to go fast to what matters right?

Revision 1513 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 347 to 347
 clear echo " Adding Musics
Changed:
<
<
    ======== == =======
>
>
    ====== ======
       Album Title:

Revision 1413 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Revision 1313 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 22 to 22
 TotCols=$(tput cols) # Number of columns of screen to frame messages echo "   Inclusion of Musics
Changed:
<
<
    ======== == =======
>
>
    ========= == ======
       Album Title:
Line: 211 to 211
 # The body of the actual program starts here clear echo "
Changed:
<
<
Adding Musics     ======== == =======
>
>
Inclusion of Musics     ========= == ======
       Album Title:
Line: 226 to 226
 do tput cup 5 38; tput el # Positions and clean row read Album
Changed:
<
<
[ ! "$Album" ] && # Operator gave <ENTER>
>
>
[ ! "$Album" ] && # Operator has hit <ENTER>
  { Question "Do you wish to finish" y n [ $SN = "n" ] && continue # Now only text to lowercase
Line: 246 to 246
  echo $Track tput cup 9 38 # Positions to read music read Music
Changed:
<
<
[ "$Music" ] || # If the operator has given <ENTER>...
>
>
[ "$Music" ] || # If the operator has hit <ENTER>...
  { Question "End of Album?" y n [ "$SN" = n ] && continue # Now only text to lowercase
Line: 476 to 476
       - Waiter, send two, mine is low foam ...
Deleted:
<
<
Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se.
 Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me. .

Thanks!

Revision 1212 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 329 to 329
 /home
Changed:
<
<
Ahh! Agora sim! Sendo passado como parâmetro do comando source ou . (ponto), o script foi executado no Shell corrente deixando neste, todo o ambiente criado. Agora damos um rewind para o início da explicação sobre este comando. Lá falamos do .bash_profile, e a esta altura você já deve saber que a sua incumbência é, logo após o login, deixar o ambiente de trabalho preparado para o usuário, e agora entendemos que é por isso mesmo que ele é executado usando este artifício.
>
>
Ahh! Now yes! Being passed as a parameter of source command or . (point), the script has been executed in the current shell leaving this, whole environment created. Now we give a rewind to the beginning of the explanation of this command. There we talked about .bash_profile, and by now you should already know that their duty is, right after login, prepared to leave the working environment for the user, and now we understand that is so even though it runs using this trick.
 
Changed:
<
<
E agora você deve estar se perguntando se é só para isso que este comando serve, e eu lhe digo que sim, mas isso nos traz um monte de vantagens e uma das mais usadas é tratar funções como rotinas externas. Veja uma outra forma de fazer o nosso programa para incluir CDs no arquivo musicas:
>
>
And now you must be asking yourself if this command does just that, and I tell you yes but it brings a lot of advantages and one of the most used is to treat functions as external routines. See another way to make our program to include CDs in file musics:
 
$ cat musinc7 #!/bin/bash
Changed:
<
<
# Cadastra CDs (versao 7)
>
>
# Registers CDs (version 7)
 #
Changed:
<
<
# Área de variáveis globais LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs
>
>
# Area of ​​global variables LineMesg=$((`tput lines` - 3)) # Line messages will be given to operator TotCols=$(tput cols) # Number of columns of screen to frame messages
 
Changed:
<
<
# O corpo do programa propriamente dito começa aqui
>
>
# The body of the actual program starts here
 clear echo "
Changed:
<
<
Inclusao de Músicas
>
>
Adding Musics
     ======== == =======    
Changed:
<
<
  Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:
>
>
  Album Title:   | This field was   Track: < created only for   | guide the fill   Music Title:
  
Changed:
<
<
  Intérprete:" # Tela montada com um único echo
>
>
  Interpreter:" # Screen mounted with a single echo
 while true do
Changed:
<
<
tput cup 5 38; tput el # Posiciona e limpa linha
>
>
tput cup 5 38; tput el # Positions and clean row
  read Album
Changed:
<
<
[ ! "$Album" ] && # Operador deu
>
>
[ ! "$Album" ] && # Operator gave
  {
Changed:
<
<
source pergunta.func "Deseja Terminar" s n [ $SN = "n" ] && continue # Agora só testo a caixa baixa clear; exit # Fim da execução
>
>
source question.func "Do you wish to finish" y n [ $SN = "n" ] && continue # Now only text to lowercase clear; exit # End of execution
  }
Changed:
<
<
grep -iq "^$Album\^" musicas 2> /dev/null &&
>
>
grep -iq "^$Album\^" musics 2> /dev/null &&
  {
Changed:
<
<
. mandamsg.func Este álbum já está cadastrado continue # Volta para ler outro álbum
>
>
. sendmsg.func This album is already registered continue # Back to read another album
  }
Changed:
<
<
Reg="$Album^" # $Reg receberá os dados de gravação oArtista= # Guardará artista anterior
>
>
Reg="$Album^" # $Reg will receive the data recording theArtist= # Will guard previous artist
  while true do
Changed:
<
<
((Faixa++))
>
>
((Track++))
  tput cup 7 38
Changed:
<
<
echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado ... { . pergunta.func "Fim de Álbum?" s n [ "$SN" = n ] && continue # Agora só testo a caixa baixa break # Sai do loop para gravar dados } tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ] && echo -n "($oArtista) " # Artista anter. é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela
>
>
echo $Track tput cup 9 38 # Positions to read music read Music [ "$Music" ] || # If the operator has given ... { . question.func "End of Album?" y n [ "$SN" = n ] && continue # Now only text to lowercase break # Exit the loop to write data } tput cup 11 38 # Positions to read Artist [ "$theArtist" ] && echo -n "($theArtist) " # Previous Artist is default read Artist [ "$Artist" ] && theArtist="$Artist" Reg="$Reg$theArtist~$Music:" # Mounting registry tput cup 9 38; tput el # Deletes the Music of the screen tput cup 11 38; tput el # Deletes the Artist of the screen
  done
Changed:
<
<
echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -o musicas # Classifica o arquivo
>
>
echo "$Reg" >> musics # Writes registry in end of file sort musics -o musics # Sorts the file
 done
Changed:
<
<
Agora o programa deu uma boa encolhida e as chamadas de função foram trocadas por arquivos externos chamados pergunta.func e mandamsg.func, que assim podem ser chamados por qualquer outro programa, desta forma reutilizando o seu código.
>
>
Now the program became smaller and function calls were exchanged for external files called question.func and sendmsg.func, which can thus be called by any other program, thus reusing your code.
 
Changed:
<
<
Por motivos meramente didáticos as execuções de pergunta.func e mandamsg.func estão sendo comandadas por source e por . (ponto) indiscriminadamente, embora prefira o source por ser mais visível desta forma dando maior legibilidade ao código e facilitando sua posterior manutenção.
>
>
For didactic reasons the executions of question.func and sendmsg.func are being commanded by source and . (point) indiscriminately, but prefers the source to be more visible thus giving greater legibility code and facilitating their subsequent maintenance.
 
Changed:
<
<
Veja agora como ficaram estes dois arquivos:
>
>
Watch how were these two files:
 
Changed:
<
<
$ cat pergunta.func # A função recebe 3 parâmetros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)"
>
>
$ cat question.func # The function takes 3 parameters in the following order: # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value # Supposing that $1=Accept?, $2=y e $3=n, the row # then put the value in message "Accept? (Y/n)"
 Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
 echo "$Msg"
Changed:
<
<
tput cup $LinhaMesg $((Col + TamMsg + 1))
>
>
tput cup $LineMesg $((Col + TamMsg + 1))
 read -n1 SN
Changed:
<
<
[ ! $SN ] && SN=$2 # Se vazia coloca default em SN echo $SN | tr A-Z a-z # A saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela $ cat mandamsg.func # A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msq entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1.
>
>
[ ! $SN ] && SN=$2 # If empty puts default on SN echo $SN | tr A-Z a-z # The output of SN will be in lowercase tput cup $LineMesg $Col; tput el #Deletes the message screen $ cat sendmsg.func # The function takes only one parameter # with the message that you want to display, # to not force the programmer to pass # the message in quotes, we'll use $* (all # parameters, remember?) and not $1.
 Msg="$*" TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
 echo "$Msg" read -n1
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen
 
Changed:
<
<
Em ambos os arquivos, fiz somente duas mudanças que veremos nas observações a seguir, porém tenho mais três a fazer:
>
>
In both files, I only made two changes that we will see in the comments below, but I have three more to do:
 
Changed:
<
<
  1. As variáveis não estão sendo mais declaradas como local, porque está é uma diretiva que só pode ser usada no corpo de funções e portanto estas variáveis permanecem no ambiente do Shell, poluindo-o;
  2. O comando return não está mais presente mas poderia estar sem alterar em nada a lógica, uma vez que ele só serviria para indicar um eventual erro via um código de retorno previamente estabelecido (por exemplo return 1, return 2, ...), sendo que o return e return 0 são idênticos e significam rotina executada sem erros;
  3. O comando que estamos acostumados a usar para gerar código de retorno é o exit, mas a saída de uma rotina externa não pode ser feita desta forma, porque por estar sendo executada no mesmo Shell que o script chamador, o exit simplesmente encerraria este Shell, terminando a execução de todo o script;
  4. De onde surgiu a variável LinhaMesg? Ela veio do musinc7, porque ela havia sido declarada antes da chamada das rotinas (nunca esquecendo que o Shell que está interpretando o script e estas rotinas é o mesmo);
  5. Se você decidir usar rotinas externas, não se avexe, abunde os comentários (principalmente sobre a passagem dos parâmetros) para facilitar a manutenção e seu uso por outros programas no futuro.
>
>
  1. The variables aren't more being declared as local, because it is a directive that can only be used in body functions and therefore these variables remain in the Shell environment, polluting it;
  2. The return command isn't longer present but could be without altering the logic, since it would only serve to indicate any error via a return code
predetermined (e.g. return 1, return 2, ...), where the return and return 0 are identical and represent routine executed without error;
  1. The command that we're accustomed to use to generate the return code is the exit, but the output of an external routine can not be done this way because to be running on the same Shell that the caller script, the exit simply would end this Shell, ending the execution of the entire script;
  2. Where did the LineMesg variable? It came from musinc7 because it had been declared before the call routines (never forgetting that Shell is interpreting the script and these routines is the same);
  3. If you decide to use external routines, do not be intimidated, concentrate in the comments (mostly about passing parameters) to facilitate the maintenance and use by other programs in the future.
 
Changed:
<
<
     - Bem, agora você já tem mais um monte de novidade para melhorar os scripts que fizemos você se lembra do programa listartista no qual você passava o nome de um artista como parâmetro e ele devolvia as suas músicas? Ele era assim:
>
>
     - Well, now you have a lot more of new scripts to improve what we did. Do you remember the program listartist in which you passed the name of an artist as a parameter and he returned their music? It was like:
 
Changed:
<
<
$ cat listartista
>
>
$ cat listartist
 #!/bin/bash
Changed:
<
<
# Dado um artista, mostra as suas musicas # versao 2
>
>
# Entered an artist, shows his musics # version 2
  if [ $# -eq 0 ] then
Changed:
<
<
echo Voce deveria ter passado pelo menos um parametro
>
>
echo You should have passed at least one parameter
  exit 1 fi

IFS=" :"

Changed:
<
<
for ArtMus in $(cut -f2 -d^ musicas)
>
>
for ArtMus in $(cut -f2 -d^ musics)
 do echo "$ArtMus" | grep -i "^$*~" > /dev/null && echo $ArtMus | cut -f2 -d~ done
Changed:
<
<
     - Claro que me lembro!...
>
>
     - Of course I remember!...
 
Changed:
<
<
     - Então para firmar os conceitos que te passei, faça ele com a tela formatada, em loop, de forma que ele só termine quando receber um <ENTER> puro no nome do artista. Ahhh! Quando a listagem atingir a antepenúltima linha da tela, o programa deverá dar uma parada para que o operador possa lê-las, isto é, suponha que a tela tenha 25 linhas. A cada 22 músicas listadas (quantidade de linhas menos 3) o programa aguardará que o operador tecle algo para então prosseguir. Eventuais mensagens de erro devem ser passadas usando a rotina mandamsg.func que acabamos de desenvolver.
>
>
     - So to establish the concepts that I gave you, do it with the formatted screen, in loop, such that it only ends when you receive a pure <ENTER> the artist's name. Ahhh! When the list reaches the penultimate line of the screen, the program should take a break for operator to can read them, that is, suppose that the screen has 25 lines. Every 22 songs listed (number of rows minus 3) the program waits for the operator to press something then proceed. Any error messages should be passed to routine sendmsg.func we just developed.
 
Changed:
<
<
     - Chico, manda mais dois, o meu é com pouca pressão...
>
>
     - Waiter, send two, mine is low foam ...
  Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se.
Changed:
<
<
Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim.
>
>
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me. .
 
Changed:
<
<
Valeu!
>
>
Thanks!

Revision 1111 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 274 to 274
 
  Body of Program  
Changed:
<
<
Esta estruturação é devido ao Shell ser uma linguagem interpretada e desta forma o programa é lido da esquerda para a direita e de cima para baixo e uma variável para ser vista simultaneamente pelo script e suas funções deve ser declarada (ou inicializada) antes de qualquer coisa. As funções por sua vez devem ser declaradas antes do corpo do programa propriamente dito porque no ponto em que o programador mencionou seu nome, o interpretador Shell já o havia antes localizado e registrado que era uma função.
>
>
This structure is due to Shell being an interpreted language and thus the program is read from left to right and from top to bottom and a variable to be viewed simultaneously by script and its functions should be declared (and initialized) before anything. The functions in turn must be declared before the body of the program itself because at the point where the programmer mentioned his name, the interpreter Shell had already located and registered before it was a function.
 
Changed:
<
<
Uma coisa bacana no uso de funções é fazê-las o mais genérico possível de forma que elas sirvam para outras aplicações, sem necessidade de serem reescritas. Essas duas que acabamos de ver têm uso generalizado, pois é difícil um script que tenha uma entrada de dados pelo teclado que não use uma rotina do tipo da MandaMsg ou não interage com o operador por algo semelhante à Pergunta.
>
>
One nice thing is the use of functions to make them as generic as possible so that they serve to other applications without the need to be rewritten. These two we just have to see generalized use because it's difficult for a script that has a data entry keyboard that doesn't use a routine type of Sendmsg or doesn't interact with the operator for something similar to Question.
 
Changed:
<
<
Conselho de amigo: crie um arquivo e cada função nova que você criar, anexe-a a este arquivo. Ao final de um tempo você terá uma bela biblioteca de funções que lhe poupará muito tempo de programação.
>
>
Friendly advice: create a file and each new function you create, attach it to this file. At the end of a time you will have a nice library of functions which will save you a lot of time programming.
 
Changed:
<
<

O comando source

>
>

The source command

 
Changed:
<
<
Vê se você nota algo de diferente na saída do ls a seguir:
>
>
See if you notice something different in output ls below:
 
$ ls -la .bash_profile -rw-r--r-- 1 Julio unknown 4511 Mar 18 17:45 .bash_profile
Changed:
<
<
Não olhe a resposta não, volte a prestar atenção! Bem, já que você está mesmo sem saco de pensar e prefere ler a resposta, vou te dar uma dica: acho que você sabe que o .bash_profile é um dos programas que são automaticamente "executados" quando você se loga (ARRGGHH! Odeio este termo). Agora que te dei esta dica olhe novamente para a saída do ls e me diga o que há de diferente nela.
>
>
Don't look at the answer, re-watch! Well, since you're no mood to think and prefer to read the answer, I'll give you a hint: think you know the .bash_profile is one of the programs that are automatically "executed" when you log (ARRGGHH! I hate this term).. Now that I gave you this tip look again at the output of ls and tell me what's different about her.
 
Changed:
<
<
Como eu disse o .bash_profile é "executado" em tempo de logon e repare que não tem nenhum direito de execução. Isso se dá porque o se você o executasse como qualquer outro script careta, quando terminasse sua execução todo o ambiente por ele gerado morreria junto com o Shell sob o qual ele foi executado (você se lembra que todos os scripts são executados em subshells, né?).
>
>
As I said the .bash_profile is "executed" in logon time and note that it has no right to run. This happens because if you execute like any other script grimace, when finished it's run around the environment generated by it die along with Shell under which it was executed (remember that all scripts are executed in subshells, right ?).
 
Changed:
<
<
Pois é. É para coisas assim que existe o comando source, também conhecido por . (ponto). Este comando faz com que não seja criado um novo Shell (um subshell) para executar o programa que que lhe é passado como parâmetro.
>
>
Well, it's for things like which exists the source command, also known as . (point). This command makes it not created a new Shell (a subshell) to run the program that it's passed as a parameter.
 
Changed:
<
<
Melhor um exemplo que 453 palavras. Veja este scriptizinho a seguir:
>
>
Better an example that 453 words. Watch this short script below:
 
Changed:
<
<
$ cat script_bobo
>
>
$ cat short_script
 cd .. ls
Changed:
<
<
Ele simplesmente deveria ir para o diretório acima do diretório atual. Vamos executar uns comandos envolvendo o script_bobo e vamos analisar os resultados:
>
>
He should just go to the directory above the current directory. Let's run a few commands involving short_script and we will analyze the results:
 
$ pwd /home/jneves
Changed:
<
<
$ script_bobo
>
>
$ short_script
 jneves juliana paula silvie $ pwd /home/jneves
Changed:
<
<
Se eu mandei ele subir um diretório, porque não subiu? Subiu sim! O subshell que foi criado para executar o script tanto subiu que listou os diretórios dos quatro usuários abaixo do /home, só que assim que o script acabou, o subshell foi para o beleleu e com ele todo o ambiente criado. Olha agora como a coisa muda:
>
>
If I sent it go up a directory, why not come up? Went up yes! The subshell which was created to run the script so much climbed which listed the directories of four users below /home, only once the script finished, the subshell was lost and with it the whole environment created. Now it looks like the thing changes:
 
Changed:
<
<
$ source script_bobo
>
>
$ source short_script
 jneves juliana paula silvie $ pwd /home $ cd - /home/jneves
Changed:
<
<
$ . script_bobo
>
>
$ . short_script
 jneves juliana paula silvie $ pwd /home

Revision 1010 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 215 to 215
     ======== == =======    
Changed:
<
<
  Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:
>
>
  Album Title:   | This field was   Track: < created only for   | guide the fill   Music Title:
  
Changed:
<
<
  Intérprete:" # Tela montada com um único echo
>
>
  Interpreter:" # Screen mounted with a single echo
 while true do
Changed:
<
<
tput cup 5 38; tput el # Posiciona e limpa linha
>
>
tput cup 5 38; tput el # Positions and clean row
  read Album
Changed:
<
<
[ ! "$Album" ] && # Operador deu <ENTER>
>
>
[ ! "$Album" ] && # Operator gave <ENTER>
  {
Changed:
<
<
Pergunta "Deseja Terminar" s n [ $SN = "n" ] && continue # Agora só testo a caixa baixa clear; exit # Fim da execução
>
>
Question "Do you wish to finish" y n [ $SN = "n" ] && continue # Now only text to lowercase clear; exit # End of execution
  }
Changed:
<
<
grep -iq "^$Album\^" musicas 2> /dev/null &&
>
>
grep -iq "^$Album\^" musics 2> /dev/null &&
  {
Changed:
<
<
    MandaMsg Este álbum já está cadastrado continue # Volta para ler outro álbum
>
>
    SendMsg This album is already registered continue # Back to read another album
  }
Changed:
<
<
Reg="$Album^" # $Reg receberá os dados de gravação oArtista= # Guardará artista anterior
>
>
Reg="$Album^" # $Reg will receive the data recording theArtist= # Will guard previous artist
  while true do
Changed:
<
<
((Faixa++))
>
>
((Track++))
  tput cup 7 38
Changed:
<
<
echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado <ENTER>...
>
>
echo $Track tput cup 9 38 # Positions to read music read Music [ "$Music" ] || # If the operator has given <ENTER>...
  {
Changed:
<
<
Pergunta "Fim de Álbum?" s n [ "$SN" = n ] && continue # Agora só testo a caixa baixa break # Sai do loop para gravar dados
>
>
Question "End of Album?" y n [ "$SN" = n ] && continue # Now only text to lowercase break # Exit the loop to write data
  }
Changed:
<
<
tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ]&& echo -n "($oArtista) " # Artista anterior é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela
>
>
tput cup 11 38 # Positions to read Artist [ "$theArtist" ]&& echo -n "($theArtist) " # Previous Artist is default read Artist [ "$Artist" ] && theArtist="$Artist" Reg="$Reg$theArtist~$Music:" # Mounting registry tput cup 9 38; tput el # Deletes the Music of the screen tput cup 11 38; tput el # Deletes the Artist of the screen
  done
Changed:
<
<
echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -o musicas # Classifica o arquivo
>
>
echo "$Reg" >> musics # Writes registry in end of file sort musics -o musics # Sorts the file
 done
Changed:
<
<
Repare que a estruturação do script está conforme o gráfico a seguir:
>
>
Note that the structure of the script is shown in the graph below:
 
Changed:
<
<
  Corpo do Programa  
Variáveis Globais
Funções
>
>
  Body of Program  
Global Variables
Functions
 

Esta estruturação é devido ao Shell ser uma linguagem interpretada e desta forma o programa é lido da esquerda para a direita e de cima para baixo e uma variável para ser vista simultaneamente pelo script e suas funções deve ser declarada (ou inicializada) antes de qualquer coisa. As funções por sua vez devem ser declaradas antes do corpo do programa propriamente dito porque no ponto em que o programador mencionou seu nome, o interpretador Shell já o havia antes localizado e registrado que era uma função.

Revision 910 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 102 to 102
 

Functions

Changed:
<
<
     - Waiter! Gimme two beers to give me inspiration, but please, not much head.
>
>
     - Waiter! Gimme two beers to give me inspiration, but please, not too much head.
 
   Question ()

Revision 810 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 102 to 102
 

Functions

Changed:
<
<
     - Waiter! Gimme two beers to give me inspiration, but please go easy on the foam.
>
>
     - Waiter! Gimme two beers to give me inspiration, but please, not much head.
 
   Question ()

Revision 710 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 102 to 102
 

Functions

Changed:
<
<
     - Waiter! Gimme two drafts to give me inspiration, but please go easy on the foam.
>
>
     - Waiter! Gimme two beers to give me inspiration, but please go easy on the foam.
 
   Question ()
Line: 111 to 111
  # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value
Changed:
<
<
# Supposing that $1=Accept?, $2=Y e $3=n, the row,
>
>
# Supposing that $1=Accept?, $2=y e $3=n, the row,
  # then put the value in message "Accept? (Y/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg?=${#Msg}
Line: 133 to 133
  The line of code that creates local Msg concatenates the received text ($1) a left parentheses, the default response ($2) in uppercase, one bar, the other answer ($3) in lowercase and finalizes with the closing parenthesis. I use this convention, at the same time, to show the available options and highlight the response offered by default.
Changed:
<
<
Quase ao fim da rotina, a resposta recebida ($SN) é passada para caixa baixa de forma que no corpo do programa não se precise fazer este teste.
>
>
Almost at the end of the routine, the answer received ($SN) is passed to lower case so that the body of the program doesn't need to do this test.
 
Changed:
<
<
Veja agora como ficaria a função para dar uma mensagem na tela:
>
>
Watch how the function would be to give a message on the screen:
 
Changed:
<
<
function MandaMsg?
>
>
function SendMsg?
  {
Changed:
<
<
# A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msq entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1.
>
>
# The function takes only one parameter # with the message that you want to display, # to not force the programmer to pass # the message in quotes, we'll use $* (all # parameters, remember?) and not $1.
  local Msg="$*" local TamMsg?=${#Msg}
Changed:
<
<
local Col=$(((TotCols? - TamMsg?) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
local Col=$(((TotCols? - TamMsg?) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg" read -n1
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen return # Exits the function.
  }
Changed:
<
<
Esta é uma outra forma de definir uma função: não a chamamos como no exemplo anterior usando uma construção com a sintaxe nome_da_função (), mas sim como function nome_da_função. Quanto ao mais, nada difere da anterior, exceto que, como consta dos comentários, usamos a variável $* que como já sabemos é o conjunto de todos os parâmetros passados, para que o programador não precise usar aspas envolvendo a mensagem que deseja passar para a função.
>
>
This is another way to define a function: not to call as in the previous example using a construction with the syntax function_name (), but as function function_name. For the rest, nothing differs from the previous one, except that, as stated in the comments, use the variable $* which as we know is the set of all of the parameters, so that the programmer does not need to use quotation marks surrounding the message you want pass to the function.
 
Changed:
<
<
Para terminar com este blá-blá-blá vamos ver então as alterações que o programa necessita quando usamos o conceito de funções:
>
>
To finish with this blah blah blah then we'll see the changes that the program needs when we use the concept of functions:
 
$ cat musinc6 #!/bin/bash
Changed:
<
<
# Cadastra CDs (versao 6)
>
>
# Registers CDs (version 6)
 #
Changed:
<
<
# Área de variáveis globais LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs
>
>
# Area of ​​global variables LineMesg=$((`tput lines` - 3)) # Line messages will be given to operator TotCols=$(tput cols) # Number of columns of screen to frame messages
 
Changed:
<
<
# Área de funções Pergunta ()
>
>
# Function Area Question ()
  {
Changed:
<
<
# A função recebe 3 parâmetros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)"
>
>
# The function takes 3 parameters in the following order: # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value # Supposing that $1=Accept?, $2=y e $3=n, the row # then put the value in message "Accept? (Y/n)"
  local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg=${#Msg}
Changed:
<
<
local Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
local Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg"
Changed:
<
<
tput cup $LinhaMesg $((Col + TamMsg + 1))
>
>
tput cup $LineMesg $((Col + TamMsg + 1))
  read -n1 SN
Changed:
<
<
[ ! $SN ] && SN=$2 # Se vazia coloca default em SN echo $SN | tr A-Z a-z # A saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função
>
>
[ ! $SN ] && SN=$2 # If empty puts default on SN echo $SN | tr A-Z a-z # The output of SN will be in lowercase tput cup $LinhaMesg $Col; tput el # Deletes the message screen return # Exits the function
  }
Changed:
<
<
function MandaMsg
>
>
function SendMsg
  {
Changed:
<
<
# A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msq entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1.
>
>
# The function takes only one parameter # with the message that you want to display, # to not force the programmer to pass # the message in quotes, we'll use $* (all # parameters, remember?) and not $1.
  local Msg="$*" local TamMsg=${#Msg}
Changed:
<
<
local Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
local Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg" read -n1
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen return # Exits the function
  }
Changed:
<
<
# O corpo do programa propriamente dito começa aqui
>
>
# The body of the actual program starts here
 clear echo "
Changed:
<
<
Inclusao de Músicas
>
>
Adding Musics
     ======== == =======    

Revision 610 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Revision 509 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 111 to 111
  # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value
Changed:
<
<
# Supposing that $1=Accept?, $2=y e $3=n, the row,
>
>
# Supposing that $1=Accept?, $2=Y e $3=n, the row,
  # then put the value in message "Accept? (Y/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg?=${#Msg}
Line: 127 to 127
  }
Changed:
<
<
Como podemos ver, uma função é definida quando fazemos nome_da_função () e todo o seu corpo está entre chaves ({}). Assim como conversamos aqui no Boteco sobre passagem de parâmetros, as funções os recebem da mesma forma, isto é, são parâmetros posicionais ($1, $2, ..., $n) e todas as regras que se aplicam a passagem de parâmetros para programas, também valem para funções, mas é muito importante realçar que os parâmetros passados para um programa não se confundem com aqueles que este passou para suas funções. Isso significa, por exemplo, que o $1 de um script é diferente do $1 de uma de suas funções
>
>
As we can see, a function is defined when we make function_name () and your whole body is in braces ({}). Just as we talked in the pub about parameter passing, the functions receive the same way, i.e. are positional parameters ($1, $2, ..., $n) and all the rules applying to passing parameters for programs, also apply to functions, but it is very important to note that the parameters passed for a program should not be confused with those who the program passed to their functions. This means, for example, that $1 of a script it's different from $1 one of it's functions.
 
Changed:
<
<
Repare que as variáveis $Msg, $TamMsg e $Col são de uso restrito desta rotina, e por isso foram criadas como local. A finalidade disso é simplesmente para economizar memória, já que ao sair da rotina, elas serão devidamente detonadas da partição e caso não tivesse usado este artifício, permaneceriam residentes.
>
>
Note that the variables $Msg, $TamMsg and $Col are restricted to use this routine, and so were created as local. The purpose of this is simply to save memory, because when exiting the routine, they will be properly detonated of the partition and if it had not used this gimmick, residents remain.
 
Changed:
<
<
A linha de código que cria local Msg, concatena ao texto recebido ($1) um abre parênteses, a resposta default ($2) em caixa alta, uma barra, a outra resposta ($3) em caixa baixa e finaliza fechando o parênteses. Uso esta convenção para, ao mesmo tempo, mostrar as opções disponíveis e realçar a resposta oferecida como default.
>
>
The line of code that creates local Msg concatenates the received text ($1) a left parentheses, the default response ($2) in uppercase, one bar, the other answer ($3) in lowercase and finalizes with the closing parenthesis. I use this convention, at the same time, to show the available options and highlight the response offered by default.
  Quase ao fim da rotina, a resposta recebida ($SN) é passada para caixa baixa de forma que no corpo do programa não se precise fazer este teste.

Revision 407 Mar 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 102 to 102
 

Functions

Changed:
<
<
     - Waiter! Now give me two beers, one without foam, to give me inspiration.
>
>
     - Waiter! Gimme two drafts to give me inspiration, but please go easy on the foam.
 
   Question ()

Revision 307 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 111 to 111
  # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value
Changed:
<
<
# Supposing that $1=Accept?, $2=s e $3=n, the row, a # seguir colocaria em Msg o valor "Aceita? (S/n)"
>
>
# Supposing that $1=Accept?, $2=y e $3=n, the row, # then put the value in message "Accept? (Y/n)"
  local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg?=${#Msg}
Changed:
<
<
local Col=$(((TotCols? - TamMsg?) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
local Col=$(((TotCols? - TamMsg?) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg"
Changed:
<
<
tput cup $LinhaMesg $((Col + TamMsg? + 1))
>
>
tput cup $LineMesg $((Col + TamMsg? + 1))
  read -n1 SN
Changed:
<
<
[ ! $SN ] && SN=$2 # Se vazia coloca default em SN echo $SN | tr A-Z a-z # A saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função
>
>
[ ! $SN ] && SN=$2 # If empty puts default on SN echo $SN | tr A-Z a-z # The output of SN will be in lowercase tput cup $LineMesg $Col; tput el # Deletes the message screen return # Exits the function.
  }

Revision 205 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part VIII


Line: 6 to 6
 
     - Hello dude! Is everything okay??
Changed:
<
<
     - Legal!, eu queria te mostrar o que fiz mas já sei que você vai querer molhar o bico primeiro né?
>
>
     - Cool! I wanted to show you what I did but I know you will want to go fast to what matters right?
 
Changed:
<
<
     - Só pra contrariar, hoje vou deixar você mostrar logo o seu "bacalho". Vai mostra aí o que você fez.
>
>
     - Just to counteract, today I'll leave you first show your work. Show me what you did.
 
Changed:
<
<
     - Poxa o exercício que você passou é muito grande. Veja só como eu resolvi:
>
>
     - Ahh ... The exercise you gave is very large. See how I solved:
 
$ cat musinc5 #!/bin/bash
Changed:
<
<
# Cadastra CDs (versao 5)
>
>
# Registers CDs (version 5)
 # clear
Changed:
<
<
LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs
>
>
LineMesg=$((`tput lines` - 3)) # Row that defines how many messages will be given to operator TotCols=$(tput cols) # Number of columns of screen to frame messages
 echo "
Changed:
<
<
  Inclusao de Músicas
>
>
  Inclusion of Musics
     ======== == =======    
Changed:
<
<
  Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:
>
>
  Album Title:   | This field was   Track: < created only for   | guide the fill   Music Title:
  
Changed:
<
<
  Intérprete:" # Tela montada com um único echo
>
>
  Interpreter:" # Screen mounted with a single echo
 while true do
Changed:
<
<
tput cup 5 38; tput el # Posiciona e limpa linha
>
>
tput cup 5 38; tput el # Positions and clean row
  read Album
Changed:
<
<
[ ! "$Album" ] && # Operador deu <ENTER>
>
>
[ ! "$Album" ] && # Operator gave <ENTER>
  {
Changed:
<
<
Msg="Deseja Terminar? (S/n)"
>
>
Msg="Do you wish to finish? (Y/n)"
         TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg"
Changed:
<
<
tput cup $LinhaMesg $((Col + TamMsg + 1))
>
>
tput cup $LineMesg $((Col + TamMsg + 1))
  read -n1 SN
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela [ $SN = "N" -o $SN = "n" ] && continue # $SN é igual a N ou (-o) n? clear; exit # Fim da execução
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen [ $SN = "N" -o $SN = "n" ] && continue # $SN is equal to N or (-o) n? clear; exit # End of execution
  }
Changed:
<
<
grep "^$Album\^" musicas > /dev/null &&
>
>
grep "^$Album\^" musics > /dev/null &&
  {
Changed:
<
<
Msg="Este álbum já está cadastrado"
>
>
Msg="This album is already registered"
         TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg" read -n1
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela continue # Volta para ler outro álbum
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen continue # Back to read another album
  }
Changed:
<
<
Reg="$Album^" # $Reg receberá os dados para gravação oArtista= # Variavel que guarda artista anterior
>
>
Reg="$Album^" # $Reg will receive the data for recording theArtist= # Variable that saves the previous artist
  while true do
Changed:
<
<
((Faixa++))
>
>
((Track++))
  tput cup 7 38
Changed:
<
<
echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado <ENTER>...
>
>
echo $Track tput cup 9 38 # Positions to read music read Music [ "$Music" ] || # If the operator has given <ENTER>...
  {
Changed:
<
<
Msg="Fim de Álbum? (S/n)"
>
>
Msg="End of Album? (Y/n)"
             TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # Centralizes message on row tput cup $LineMesg $Col
  echo "$Msg"
Changed:
<
<
tput cup $LinhaMesg $((Col + TamMsg + 1)
>
>
tput cup $LineMesg $((Col + TamMsg + 1)
  read -n1 SN
Changed:
<
<
tput cup $LinhaMesg $Col; tput el # Apaga msg da tela [ "$SN" = N -o "$SN" = n ]&&continue # $SN é igual a N ou (-o) n? break # Sai do loop para gravar
>
>
tput cup $LineMesg $Col; tput el # Deletes the message screen [ "$SN" = N -o "$SN" = n ]&&continue # $SN is equal to N or (-o) n? break # Exits the loop to record
  }
Changed:
<
<
tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ]&& echo -n "($oArtista) " # Artista anterior é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela
>
>
tput cup 11 38 # Positions to read Artist [ "$theArtist" ]&& echo -n "($theArtist) " # Previous Artist is default read Artist [ "$Artist" ] && theArtist="$Artist" Reg="$Reg$theArtist~$Music:" # Mounting registry tput cup 9 38; tput el # Deletes the Music of the screen tput cup 11 38; tput el # Deletes Artist of the screen
  done
Changed:
<
<
echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -0 musicas # Classifica o arquivo
>
>
echo "$Reg" >> musics # Writes registry in end of file sort musics -0 musics # Sorts the file
 done
Changed:
<
<
     - É o programa tá legal, tá todo estruturadinho, mas gostaria de alguns poucos comentários sobre o que você fez:
>
>
     - The program is cool, it's structured, but I will mention a few comments about what you did:
 
Changed:
<
<
  • Só para relembrar, as seguintes construções: [ ! $Album ] && e [ $Musica ] || representam a mesma coisa, isto é, no caso da primeira, o testamos se a variável $Album não (!) tem nada dentro, então (&&) ... Na segunda, testamos se $Musica tem dado, senão (||) ...
  • Se você reclamou do tamanho dele, é porque ainda não dei algumas dicas. Repare que a maior parte do script é para dar mensagens centradas na penúltima linha da tela. Repare ainda que algumas mensagens pedem um S ou um N e outras são só de advertência. Seria o caso típico do uso de funções, que seriam escritas somente uma vez e chamada a execução de diversos pontos do script. Vou montar duas funções para resolver estes casos e vamos incorporá-las ao seu programa para ver o resultado final.
>
>
  • Just to remind, the following constructs: [ ! $Album] && and [ $Music ] || represent the same thing, that is, in the first case, we tested if the variable $Album not (!) have nothing inside, then (&&) ... In the second, we tested if $Music has given, if not (||) ...
  • If you complained about the size of it, it's because I still did not give some tips. Note that most of the script is to provide messages centered on the penultimate row of the screen. Notice also that some messages asking for a Y or an N and others are only warning. This would be the typical case of the use of functions, which would be written only once and called the execution of several points in the script. I'll mount two functions to solve these cases and we will incorporate them into your program to see the end result.
 
Changed:
<
<

Funções

>
>

Functions

 
Changed:
<
<
     - Chico! Agora traz dois chopes, sendo um sem colarinho, para me dar inspiração.
>
>
     - Waiter! Now give me two beers, one without foam, to give me inspiration.
 
Changed:
<
<
Pergunta ()
>
>
Question ()
  {
Changed:
<
<
# A função recebe 3 parâmetros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha a
>
>
# The function takes 3 parameters in the following order: # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value # Supposing that $1=Accept?, $2=s e $3=n, the row, a
  # seguir colocaria em Msg o valor "Aceita? (S/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg?=${#Msg}

Revision 105 Mar 2014 - Main.AngelaFerreira

Line: 1 to 1
Added:
>
>
META TOPICPARENT name="WebHome"

Pub Talk Part VIII



     - Hello dude! Is everything okay??

     - Legal!, eu queria te mostrar o que fiz mas já sei que você vai querer molhar o bico primeiro né?

     - Só pra contrariar, hoje vou deixar você mostrar logo o seu "bacalho". Vai mostra aí o que você fez.

     - Poxa o exercício que você passou é muito grande. Veja só como eu resolvi:

$ cat musinc5 #!/bin/bash # Cadastra CDs (versao 5) # clear LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs echo "   Inclusao de Músicas     ======== == =======       Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:     Intérprete:" # Tela montada com um único echo while true do tput cup 5 38; tput el # Posiciona e limpa linha read Album [ ! "$Album" ] && # Operador deu <ENTER> { Msg="Deseja Terminar? (S/n)"         TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" tput cup $LinhaMesg $((Col + TamMsg + 1)) read -n1 SN tput cup $LinhaMesg $Col; tput el # Apaga msg da tela [ $SN = "N" -o $SN = "n" ] && continue # $SN é igual a N ou (-o) n? clear; exit # Fim da execução } grep "^$Album\^" musicas > /dev/null && { Msg="Este álbum já está cadastrado"         TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" read -n1 tput cup $LinhaMesg $Col; tput el # Apaga msg da tela continue # Volta para ler outro álbum } Reg="$Album^" # $Reg receberá os dados para gravação oArtista= # Variavel que guarda artista anterior while true do ((Faixa++)) tput cup 7 38 echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado <ENTER>... { Msg="Fim de Álbum? (S/n)"             TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" tput cup $LinhaMesg $((Col + TamMsg + 1) read -n1 SN tput cup $LinhaMesg $Col; tput el # Apaga msg da tela [ "$SN" = N -o "$SN" = n ]&&continue # $SN é igual a N ou (-o) n? break # Sai do loop para gravar } tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ]&& echo -n "($oArtista) " # Artista anterior é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela done echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -0 musicas # Classifica o arquivo done

     - É o programa tá legal, tá todo estruturadinho, mas gostaria de alguns poucos comentários sobre o que você fez:

  • Só para relembrar, as seguintes construções: [ ! $Album ] && e [ $Musica ] || representam a mesma coisa, isto é, no caso da primeira, o testamos se a variável $Album não (!) tem nada dentro, então (&&) ... Na segunda, testamos se $Musica tem dado, senão (||) ...
  • Se você reclamou do tamanho dele, é porque ainda não dei algumas dicas. Repare que a maior parte do script é para dar mensagens centradas na penúltima linha da tela. Repare ainda que algumas mensagens pedem um S ou um N e outras são só de advertência. Seria o caso típico do uso de funções, que seriam escritas somente uma vez e chamada a execução de diversos pontos do script. Vou montar duas funções para resolver estes casos e vamos incorporá-las ao seu programa para ver o resultado final.

Funções

     - Chico! Agora traz dois chopes, sendo um sem colarinho, para me dar inspiração.

    Pergunta ()
        {
        #  A função recebe 3 parâmetros na seguinte ordem:
        #  $1 - Mensagem a ser dada na tela
        #  $2 - Valor a ser aceito com resposta default
        #  $3 - O outro valor aceito
        #  Supondo que $1=Aceita?, $2=s e $3=n, a linha a
        #  seguir colocaria em Msg o valor "Aceita? (S/n)"
        local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)"
        local TamMsg=${#Msg}
        local Col=$(((TotCols - TamMsg) / 2))  # Centra msg na linha
        tput cup $LinhaMesg $Col
        echo "$Msg"
        tput cup $LinhaMesg $((Col + TamMsg + 1))
        read -n1 SN
        [ ! $SN ] && SN=$2                     # Se vazia coloca default em SN
        echo $SN | tr A-Z a-z                  # A saída de SN será em minúscula
        tput cup $LinhaMesg $Col; tput el      # Apaga msg da tela
        return                                 # Sai da função
        }

Como podemos ver, uma função é definida quando fazemos nome_da_função () e todo o seu corpo está entre chaves ({}). Assim como conversamos aqui no Boteco sobre passagem de parâmetros, as funções os recebem da mesma forma, isto é, são parâmetros posicionais ($1, $2, ..., $n) e todas as regras que se aplicam a passagem de parâmetros para programas, também valem para funções, mas é muito importante realçar que os parâmetros passados para um programa não se confundem com aqueles que este passou para suas funções. Isso significa, por exemplo, que o $1 de um script é diferente do $1 de uma de suas funções

Repare que as variáveis $Msg, $TamMsg e $Col são de uso restrito desta rotina, e por isso foram criadas como local. A finalidade disso é simplesmente para economizar memória, já que ao sair da rotina, elas serão devidamente detonadas da partição e caso não tivesse usado este artifício, permaneceriam residentes.

A linha de código que cria local Msg, concatena ao texto recebido ($1) um abre parênteses, a resposta default ($2) em caixa alta, uma barra, a outra resposta ($3) em caixa baixa e finaliza fechando o parênteses. Uso esta convenção para, ao mesmo tempo, mostrar as opções disponíveis e realçar a resposta oferecida como default.

Quase ao fim da rotina, a resposta recebida ($SN) é passada para caixa baixa de forma que no corpo do programa não se precise fazer este teste.

Veja agora como ficaria a função para dar uma mensagem na tela:

    function MandaMsg
        {
        # A função recebe somente um parâmetro
        # com a mensagem que se deseja exibir,
        # para não obrigar ao programador passar
        # a msq entre aspas, usaremos $* (todos
        # os parâmetro, lembra?) e não $1.
        local Msg="$*"
        local TamMsg=${#Msg}
        local Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha
        tput cup $LinhaMesg $Col
        echo "$Msg"
        read -n1
        tput cup $LinhaMesg $Col; tput el     # Apaga msg da tela
        return                                # Sai da função
        }

Esta é uma outra forma de definir uma função: não a chamamos como no exemplo anterior usando uma construção com a sintaxe nome_da_função (), mas sim como function nome_da_função. Quanto ao mais, nada difere da anterior, exceto que, como consta dos comentários, usamos a variável $* que como já sabemos é o conjunto de todos os parâmetros passados, para que o programador não precise usar aspas envolvendo a mensagem que deseja passar para a função.

Para terminar com este blá-blá-blá vamos ver então as alterações que o programa necessita quando usamos o conceito de funções:

$ cat musinc6 #!/bin/bash # Cadastra CDs (versao 6) #

# Área de variáveis globais LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs

# Área de funções Pergunta () { # A função recebe 3 parâmetros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" tput cup $LinhaMesg $((Col + TamMsg + 1)) read -n1 SN [ ! $SN ] && SN=$2 # Se vazia coloca default em SN echo $SN | tr A-Z a-z # A saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função } function MandaMsg { # A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msq entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1. local Msg="$*" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" read -n1 tput cup $LinhaMesg $Col; tput el # Apaga msg da tela return # Sai da função }

# O corpo do programa propriamente dito começa aqui clear echo " Inclusao de Músicas     ======== == =======       Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:     Intérprete:" # Tela montada com um único echo while true do tput cup 5 38; tput el # Posiciona e limpa linha read Album [ ! "$Album" ] && # Operador deu <ENTER> { Pergunta "Deseja Terminar" s n [ $SN = "n" ] && continue # Agora só testo a caixa baixa clear; exit # Fim da execução } grep -iq "^$Album\^" musicas 2> /dev/null && {     MandaMsg Este álbum já está cadastrado continue # Volta para ler outro álbum } Reg="$Album^" # $Reg receberá os dados de gravação oArtista= # Guardará artista anterior while true do ((Faixa++)) tput cup 7 38 echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado <ENTER>... { Pergunta "Fim de Álbum?" s n [ "$SN" = n ] && continue # Agora só testo a caixa baixa break # Sai do loop para gravar dados } tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ]&& echo -n "($oArtista) " # Artista anterior é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela done echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -o musicas # Classifica o arquivo done

Repare que a estruturação do script está conforme o gráfico a seguir:

  Corpo do Programa  
Variáveis Globais
Funções

Esta estruturação é devido ao Shell ser uma linguagem interpretada e desta forma o programa é lido da esquerda para a direita e de cima para baixo e uma variável para ser vista simultaneamente pelo script e suas funções deve ser declarada (ou inicializada) antes de qualquer coisa. As funções por sua vez devem ser declaradas antes do corpo do programa propriamente dito porque no ponto em que o programador mencionou seu nome, o interpretador Shell já o havia antes localizado e registrado que era uma função.

Uma coisa bacana no uso de funções é fazê-las o mais genérico possível de forma que elas sirvam para outras aplicações, sem necessidade de serem reescritas. Essas duas que acabamos de ver têm uso generalizado, pois é difícil um script que tenha uma entrada de dados pelo teclado que não use uma rotina do tipo da MandaMsg ou não interage com o operador por algo semelhante à Pergunta.

Conselho de amigo: crie um arquivo e cada função nova que você criar, anexe-a a este arquivo. Ao final de um tempo você terá uma bela biblioteca de funções que lhe poupará muito tempo de programação.

O comando source

Vê se você nota algo de diferente na saída do ls a seguir:

$ ls -la .bash_profile -rw-r--r-- 1 Julio unknown 4511 Mar 18 17:45 .bash_profile

Não olhe a resposta não, volte a prestar atenção! Bem, já que você está mesmo sem saco de pensar e prefere ler a resposta, vou te dar uma dica: acho que você sabe que o .bash_profile é um dos programas que são automaticamente "executados" quando você se loga (ARRGGHH! Odeio este termo). Agora que te dei esta dica olhe novamente para a saída do ls e me diga o que há de diferente nela.

Como eu disse o .bash_profile é "executado" em tempo de logon e repare que não tem nenhum direito de execução. Isso se dá porque o se você o executasse como qualquer outro script careta, quando terminasse sua execução todo o ambiente por ele gerado morreria junto com o Shell sob o qual ele foi executado (você se lembra que todos os scripts são executados em subshells, né?).

Pois é. É para coisas assim que existe o comando source, também conhecido por . (ponto). Este comando faz com que não seja criado um novo Shell (um subshell) para executar o programa que que lhe é passado como parâmetro.

Melhor um exemplo que 453 palavras. Veja este scriptizinho a seguir:

$ cat script_bobo cd .. ls

Ele simplesmente deveria ir para o diretório acima do diretório atual. Vamos executar uns comandos envolvendo o script_bobo e vamos analisar os resultados:

$ pwd /home/jneves $ script_bobo jneves juliana paula silvie $ pwd /home/jneves

Se eu mandei ele subir um diretório, porque não subiu? Subiu sim! O subshell que foi criado para executar o script tanto subiu que listou os diretórios dos quatro usuários abaixo do /home, só que assim que o script acabou, o subshell foi para o beleleu e com ele todo o ambiente criado. Olha agora como a coisa muda:

$ source script_bobo jneves juliana paula silvie $ pwd /home $ cd - /home/jneves $ . script_bobo jneves juliana paula silvie $ pwd /home

Ahh! Agora sim! Sendo passado como parâmetro do comando source ou . (ponto), o script foi executado no Shell corrente deixando neste, todo o ambiente criado. Agora damos um rewind para o início da explicação sobre este comando. Lá falamos do .bash_profile, e a esta altura você já deve saber que a sua incumbência é, logo após o login, deixar o ambiente de trabalho preparado para o usuário, e agora entendemos que é por isso mesmo que ele é executado usando este artifício.

E agora você deve estar se perguntando se é só para isso que este comando serve, e eu lhe digo que sim, mas isso nos traz um monte de vantagens e uma das mais usadas é tratar funções como rotinas externas. Veja uma outra forma de fazer o nosso programa para incluir CDs no arquivo musicas:

$ cat musinc7 #!/bin/bash # Cadastra CDs (versao 7) #

# Área de variáveis globais LinhaMesg=$((`tput lines` - 3)) # Linha que msgs serão dadas para operador TotCols=$(tput cols) # Qtd colunas da tela para enquadrar msgs

# O corpo do programa propriamente dito começa aqui clear echo " Inclusao de Músicas     ======== == =======       Título do Álbum:   | Este campo foi   Faixa: < criado somente para   | orientar o preenchimento   Nome da Música:     Intérprete:" # Tela montada com um único echo while true do tput cup 5 38; tput el # Posiciona e limpa linha read Album [ ! "$Album" ] && # Operador deu { source pergunta.func "Deseja Terminar" s n [ $SN = "n" ] && continue # Agora só testo a caixa baixa clear; exit # Fim da execução } grep -iq "^$Album\^" musicas 2> /dev/null && { . mandamsg.func Este álbum já está cadastrado continue # Volta para ler outro álbum } Reg="$Album^" # $Reg receberá os dados de gravação oArtista= # Guardará artista anterior while true do ((Faixa++)) tput cup 7 38 echo $Faixa tput cup 9 38 # Posiciona para ler musica read Musica [ "$Musica" ] || # Se o operador tiver dado ... { . pergunta.func "Fim de Álbum?" s n [ "$SN" = n ] && continue # Agora só testo a caixa baixa break # Sai do loop para gravar dados } tput cup 11 38 # Posiciona para ler Artista [ "$oArtista" ] && echo -n "($oArtista) " # Artista anter. é default read Artista [ "$Artista" ] && oArtista="$Artista" Reg="$Reg$oArtista~$Musica:" # Montando registro tput cup 9 38; tput el # Apaga Musica da tela tput cup 11 38; tput el # Apaga Artista da tela done echo "$Reg" >> musicas # Grava registro no fim do arquivo sort musicas -o musicas # Classifica o arquivo done

Agora o programa deu uma boa encolhida e as chamadas de função foram trocadas por arquivos externos chamados pergunta.func e mandamsg.func, que assim podem ser chamados por qualquer outro programa, desta forma reutilizando o seu código.

Por motivos meramente didáticos as execuções de pergunta.func e mandamsg.func estão sendo comandadas por source e por . (ponto) indiscriminadamente, embora prefira o source por ser mais visível desta forma dando maior legibilidade ao código e facilitando sua posterior manutenção.

Veja agora como ficaram estes dois arquivos:

$ cat pergunta.func # A função recebe 3 parâmetros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)" Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" tput cup $LinhaMesg $((Col + TamMsg + 1)) read -n1 SN [ ! $SN ] && SN=$2 # Se vazia coloca default em SN echo $SN | tr A-Z a-z # A saída de SN será em minúscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela $ cat mandamsg.func # A função recebe somente um parâmetro # com a mensagem que se deseja exibir, # para não obrigar ao programador passar # a msq entre aspas, usaremos $* (todos # os parâmetro, lembra?) e não $1. Msg="$*" TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Centra msg na linha tput cup $LinhaMesg $Col echo "$Msg" read -n1 tput cup $LinhaMesg $Col; tput el # Apaga msg da tela

Em ambos os arquivos, fiz somente duas mudanças que veremos nas observações a seguir, porém tenho mais três a fazer:

  1. As variáveis não estão sendo mais declaradas como local, porque está é uma diretiva que só pode ser usada no corpo de funções e portanto estas variáveis permanecem no ambiente do Shell, poluindo-o;
  2. O comando return não está mais presente mas poderia estar sem alterar em nada a lógica, uma vez que ele só serviria para indicar um eventual erro via um código de retorno previamente estabelecido (por exemplo return 1, return 2, ...), sendo que o return e return 0 são idênticos e significam rotina executada sem erros;
  3. O comando que estamos acostumados a usar para gerar código de retorno é o exit, mas a saída de uma rotina externa não pode ser feita desta forma, porque por estar sendo executada no mesmo Shell que o script chamador, o exit simplesmente encerraria este Shell, terminando a execução de todo o script;
  4. De onde surgiu a variável LinhaMesg? Ela veio do musinc7, porque ela havia sido declarada antes da chamada das rotinas (nunca esquecendo que o Shell que está interpretando o script e estas rotinas é o mesmo);
  5. Se você decidir usar rotinas externas, não se avexe, abunde os comentários (principalmente sobre a passagem dos parâmetros) para facilitar a manutenção e seu uso por outros programas no futuro.

     - Bem, agora você já tem mais um monte de novidade para melhorar os scripts que fizemos você se lembra do programa listartista no qual você passava o nome de um artista como parâmetro e ele devolvia as suas músicas? Ele era assim:

$ cat listartista #!/bin/bash # Dado um artista, mostra as suas musicas # versao 2

if [ $# -eq 0 ] then echo Voce deveria ter passado pelo menos um parametro exit 1 fi

IFS=" :" for ArtMus in $(cut -f2 -d^ musicas) do echo "$ArtMus" | grep -i "^$*~" > /dev/null && echo $ArtMus | cut -f2 -d~ done

     - Claro que me lembro!...

     - Então para firmar os conceitos que te passei, faça ele com a tela formatada, em loop, de forma que ele só termine quando receber um <ENTER> puro no nome do artista. Ahhh! Quando a listagem atingir a antepenúltima linha da tela, o programa deverá dar uma parada para que o operador possa lê-las, isto é, suponha que a tela tenha 25 linhas. A cada 22 músicas listadas (quantidade de linhas menos 3) o programa aguardará que o operador tecle algo para então prosseguir. Eventuais mensagens de erro devem ser passadas usando a rotina mandamsg.func que acabamos de desenvolver.

     - Chico, manda mais dois, o meu é com pouca pressão...

Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se.

Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim.

Valeu!

 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL? Send feedback