Difference: TWikiBarChiacchiere003 (1 vs. 6)

Revision 620 Feb 2013 - AlbertoTaddei

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

Line: 63 to 63
 9875789
Changed:
<
<
Come si vede, ci sono quattro sintassi distinte: nella prima (-c 1-5), ho specificato un intervallo, nella seconda (-c -6), ho specificato tutto fino a una certa posizione, nella terza (-c 4-) da una determinata posizione in poi e nella quarta (-c 1,3,5,7,9), determinate posizioni. L'ultima (-c -3,5,8-) è soltanto per farti vedere che possiamo mescolarle.
>
>
Come si vede, ci sono quattro sintassi distinte: nella prima (-c 1-5), ho specificato un intervallo, nella seconda (-c -6), ho specificato tutto fino a una certa posizione, nella terza (-c 4-) da una determinata posizione in poi e nella quarta (-c 1,3,5,7,9), determinate posizioni. L'ultima (-c -3,5,8-) è soltanto per farti vedere che possiamo anche mescolarle.
 

Il comando cut con l'opzione -f

Changed:
<
<
Non pensare che sia tutto qui! Come avrai capito, questa forma di cut è utile quanto si maneggiano file con campi a grandezza fissa, ma nella realtà si hanno di solito file con campi a grandezza variabile ognuno dei quali termina con un delimitatore. Diamo un'occhiata al file canzoni che abbiamo iniziato a metter in piedi l'ultima volta che abbiamo fatto due chiacchiere qui al bar.
>
>
Non pensare che sia tutto qui! Come avrai capito, questa forma di cut è utile quanto si maneggiano file con campi a grandezza fissa, ma nella realtà si hanno di solito file con campi a grandezza variabile ognuno dei quali termina con un delimitatore. Diamo un'occhiata al file canzoni che abbiamo iniziato a metter in piedi l'ultima volta che ci siamo visti qui al bar.
 
$ cat canzoni
Line: 77 to 77
 disco 4^Artista7~Canzone7:Artista8~Canzone8
Changed:
<
<
Quindi, ricapitolando, il suo "leiaut" è il seguente:
>
>
Quindi, ricapitolando, il "leiaut" è il seguente:
       titolo del disco^interprete1~titolo della canzone1:...:interpreten~titolo della canzonen
Changed:
<
<
cioè il titolo del disco sarà separato con un accento circonflesso (^) dal resto del registro, il quale è costituito da diversi gruppi composti dall'interprete di ogni canzone del CD e la rispettiva canzone interpretata. Questi gruppi sono separati l'uno dall'altro con i due-punti (:) e, al loro interno, il nome dell'interprete sarà separato dal titolo della canzone con una tilde (~).
>
>
cioè il titolo del disco sarà separato con un accento circonflesso (^) dal resto del registro, il quale è costituito da diversi gruppi composti dall'interprete di ogni canzone del CD e dalla canzone interpretata. Questi gruppi sono separati l'uno dall'altro per mezzi di due-punti (:) e, al loro interno, il nome dell'interprete sarà separato dal titolo della canzone tramite una tilde (~).
 
Changed:
<
<
Detto questo, per selezionare i dati riferiti a tutte le seconde canzoni del file canzoni, dobbiamo digitare:
>
>
Detto questo, per selezionare i dati relativi a tutte le seconde canzoni del file canzoni, dobbiamo digitare:
 
$ cut -f2 -d: canzoni
Line: 110 to 110
 disco 1^Artista1~Canzone1:Artista2~Canzone2
Changed:
<
<
Quindi osserva ciò che abbiamo fatto.
>
>
Adesso osserva ciò che abbiamo fatto:
  Delimitatore del primo cut (:)

     disco 1^Artista1~Canzone1:Artista2~Canzone2

Changed:
<
<
In questo modo, nel primo cut, il primo campo del delimitatore (-d) due-punti (:) è disco 1^Artista1~Canzone1 e il secondo, che è o quello che ci in interessa, è Artista2~Canzone2.
>
>
In questo modo, nel primo cut, il primo campo del delimitatore (-d) due-punti (:) è disco 1^Artista1~Canzone1 e il secondo, che è quello che ci interessa, è Artista2~Canzone2.
  Vediamo allora cosa succede con il secondo cut:
Line: 124 to 125
       Artista2~Canzone2
Changed:
<
<
Adesso, il primo campo del delimitatore (-d) tilde (~), che è quello che ci interessa, è Artista2 e il secondo è Canzone2.
>
>
Adesso, il primo campo del delimitatore (-d) tilde (~), che è quello che ci interessa, è Artista2, mentre il secondo è Canzone2.
  Se applicheremo al resto del file il ragionamento fatto per la prima riga, arriveremo alla risposta data in precedenza.

Se c'è cut c'è paste

Changed:
<
<
Come potevamo aspettarci, il comando paste serve per incollare, solo che nella Shell ciò che si incolla sono file. Per iniziare a capire come funziona, digitiamo:
>
>
Come potevamo aspettarci, il comando paste serve per incollare, solo che nella Shell si incollano file. Per iniziare a capire come funziona, digitiamo:
 
    paste file1 file2
Line: 145 to 146
 $ seq 2 2 10 > pari
Changed:
<
<
Per vedere il contenuto dei file generati, usiamo paste nella forma che abbiamo illustrato prima:
>
>
Per vedere il contenuto dei file generati, usiamo paste nella forma semplice che abbiamo illustrato prima:
 
$ paste interi pari
Line: 163 to 164
 

Chi sta in piedi prima o poi si stende

Changed:
<
<
Adesso trasformiamo la colonna dei pari nella riga:
>
>
Adesso trasformiamo la colonna dei pari in una riga:
 
$ paste -s pari 2 4 6 8 10
Changed:
<
<

Uso dei separatori

>
>

Utilizzare i separatori

  Come abbiamo già detto, il separatore di default di paste è <TAB>, ma possiamo cambiarlo con l'opzione -d. Di conseguenza, per calcolare la somma del contenuto di pari digiteremo:
Line: 210 to 211
 file4 file5 file6
Changed:
<
<
Questo risultato si ottiene perché, inserendo i segni meno(-) invece di specificare i file, il comando paste li sostituisce con lo Standard Output o lo Standard Input a seconda del caso. Nell'esempio precedente, i dati sono stati inviati allo Standard Output (stdout) poiché la pipe (|) redireziona l'output di ls allo Standard Input (stdin) di paste, ma dai un'occhiata all'esempio seguente:
>
>
Questo risultato si ottiene perché, inserendo i segni meno (-) invece di specificare i file, il comando paste li sostituisce con lo Standard Output o lo Standard Input a seconda del caso. Nell'esempio precedente, i dati sono stati inviati allo Standard Output (stdout) poiché la pipe (|) redireziona l'output di ls allo Standard Input (stdin) di paste, ma da' un'occhiata all'esempio seguente:
 
$ cat file1
Line: 231 to 232
 

Il Comando tr

Changed:
<
<
Un altro comando molto interessante è o tr il quale serve per sostituire, comprimere o rimuovere caratteri. La sua sintassi segue lo schema sottoindicato:
>
>
Un altro comando molto interessante è tr, il quale serve per sostituire, comprimere o rimuovere caratteri. La sua sintassi segue lo schema sottoindicato:
 
    tr [opzioni] stringa1 [stringa2]
Changed:
<
<
Il comando tr copia il testo dello Standard Input (stdin), sostituisce le occorrenze dei caratteri di stringa1 con i suoi corrispondenti di stringa2 o sostituisce occorrenze multiple di caratteri di stringa1 con un solo carattere, oppure rimuove caratteri da stringa1.
>
>
Il comando tr copia il testo dello Standard Input (stdin), sostituisce le occorrenze dei caratteri di stringa1 con i corrispondenti di stringa2 o sostituisce occorrenze multiple di caratteri di stringa1 con un solo carattere, oppure rimuove caratteri da stringa1.
  Le principali opzioni del comando sono:
Line: 318 to 319
 echo leggi Programmazione Shell Linux do Julio Cezar Neves pwd ls
Changed:
<
<
rm -f lixo 2>/dev/null
>
>
rm -f robaccia 2>/dev/null
 cd ~
Changed:
<
<
Il tizio ci restò male perché in 2 o 3 secondi smontai il bello scherzo per mettere su il quale aveva sprecato tanto tempo.
>
>
Il tizio ci restò male perché in 2 o 3 secondi avevo rovinato il bello scherzo per mettere su il quale aveva sprecato tanto tempo.
  Ma attento! Se avessi avuto una macchina con Unix avrei dovuto digitare:
Line: 362 to 363
 Sun Sep 5 10:12:33 2004
Changed:
<
<
Come puoi notare, ci sono 2 spazi prima di 5 (giorno), cosa che rovina tutto perché il terzo pezzo è vuoto e il quarto è il giorno (5). L'ideale sarebbe comprimere gli spazi in sequenza in uno soltanto per trattare le due stringhe risultanti dal comando date allo stesso modo, e questo si ottiene digitando:
>
>
Come puoi notare, ci sono 2 spazi prima di 5 (giorno), cosa che rovina tutto perché il terzo pezzo è vuoto e il quarto è il giorno (5). L'ideale sarebbe comprimere gli spazi in sequenza in uno soltanto per trattare le due stringhe risultanti dal comando date allo stesso modo, e ciò si ottiene digitando:
 
$ date | tr -s " "
Line: 432 to 433
 

Penguin con un piatto di attenzione
Changed:
<
<
Ciò si è verificato perché l' ftp è stato fatto in modo binario (o image), cioè senza interpretazione del testo. Se prima della trasmissione del file fosse stata stabilita l'opzione ascii dell' ftp, tutto questo non si sarebbe verificato.
>
>
Ciò si è verificato perché l' ftp è stato fatto in modo binario (o image), cioè senza interpretazione del testo. Se prima della trasmissione del file fosse stata stabilita l'opzione ascii dell' ftp, ciò non si sarebbe verificato.
 

     - Dopo queste dritte la Shell inizia quasi a piacermi, ma ci sono ancora un sacco di cose che non so fare.

Changed:
<
<
     - È vero, finora non ti ho detto quasi niente sulla programmazione Shell e hai ancora molto da imparare, ma quello che sai è sufficiente per risolvere molti problemi una volta acquisito il “modo Shell di pensare”. Saresti capace di buttare giù uno script per dirmi chi sono le persone “loggate” da più di un giorno sul tuo server?
>
>
     - È vero, finora non ti ho detto quasi niente sulla programmazione Shell e hai ancora molto da imparare, ma ciò che sai è sufficiente per risolvere molti problemi una volta acquisito il “modo Shell di pensare”. Saresti capace di buttare giù uno script per dirmi chi sono le persone “loggate” da più di un giorno sul tuo server?
       - Certo che no! Per farlo dovrei conoscere i comandi condizionali che ancora non mi hai spiegato come funzionano.
Line: 479 to 480
 $ Data=$(date | cut -c 5-10)
Changed:
<
<
Ho usato il costrutto $(...), per rendere prioritaria l'esecuzione dei comandi prima di attribuire il loro output alla variabile $Data. Vediamo se funziona:
>
>
Ho usato il costrutto $(...) per rendere prioritaria l'esecuzione dei comandi prima di attribuire il loro output alla variabile $Data. Vediamo se funziona:
 
$ echo $Data
Line: 560 to 561
  cioè: se il comando cmd è stato eseguito con successo, i comandi del blocco di then (cmd1, cmd2 e cmdn) saranno eseguiti, altrimenti i comandi da eseguire saranno quelli del blocco opzionale di else (cmd3, cmd4 e cmdm): iltutto termina con fi.
Changed:
<
<
Vediamo come tutto questo funzionabcon un piccolo script che serve a inserire gli utenti in /etc/passwd:
>
>
Vediamo come tutto ciò funziona utilizando un piccolo script che serve a inserire gli utenti in /etc/passwd:
 
$ cat inserutente
Line: 568 to 569
 # Versione 1 if grep ^$1 /etc/passwd then
Changed:
<
<
echo L'utente \'$1\' è già presente
>
>
echo L'utente \'$1\' esiste già
 else if useradd $1 then
Line: 588 to 589
 L'utente 'jneves' è già presente
Changed:
<
<
Come abbiamo visto in precedenza, ma è sempre meglio ripetere affinché tu stia attento, nell'esempio è spuntata fuori una riga indesiderata che altro non è che l'output del comando grep. Per evitare che questo accada, dobbiamo redirigere l'output di questa istruzione in /dev/null:
>
>
Come abbiamo già visto in precedenza (ma è sempre meglio ripetere affinché tu stia attento), nell'esempio è spuntata fuori una riga indesiderata che altro non è che l'output del comando grep. Per evitare che questo accada, dobbiamo redirigere l'output di questa istruzione in /dev/null:
 
$ cat inserutente
Line: 596 to 597
 # Versione 2 if grep ^$1 /etc/passwd > /dev/null # ou: if grep -q ^$1 /etc/passwd then
Changed:
<
<
echo L'utente \'$1\' è già presente
>
>
echo L'utente \'$1\' esiste già
 else if useradd $1 then
Line: 625 to 626
 # Versione 3 if grep ^$1 /etc/passwd > /dev/null then
Changed:
<
<
echo L'utente \'$1\' è già presente
>
>
echo L'utente \'$1\' esiste già
 else if useradd $1 2> /dev/null then
Line: 647 to 648
 
$ inserutente botelho
Changed:
<
<
L'utente 'botelho' è già presente
>
>
L'utente 'botelho' esiste già
 
Changed:
<
<
Ricordi che ti ho detto che, tra una chiacchiera e una birra, i nostri programmi sarebbero diventati più raffinati? Vediamo come possiamo migliorare il nostro programma per registrare le canzoni:
>
>
Ricordi che ti ho detto, tra una chiacchiera e una birra, che i nostri programmi sarebbero diventati più raffinati? Vediamo come possiamo migliorare il nostro programma per registrare le canzoni:
 
$ cat insercanz
Line: 666 to 667
 fi
Changed:
<
<
Come puoi vedere si tratta di una piccola variazione della versione precedente: adesso, prima di inserire un record, (che nella versione precedente poteva essere duplicato), controlliamo se il record inizia (^) e finisce ($) allo stesso modo del parametro immesso ($1). L'accento circonflesso (^) all'inizio della stringa e il dollaro ($) alla fine servono a testare se il parametro immesso (il disco e i suoi dati) è esattamente uguale a qualche altro record già inserito e non soltanto uguale a una parte di qualche record.
>
>
Come puoi vedere, si tratta di una piccola variazione della versione precedente: adesso, prima di inserire un record (che nella versione precedente poteva essere duplicato), controlliamo se il record inizia (^) e finisce ($) allo stesso modo del parametro immesso ($1). L'accento circonflesso (^) all'inizio della stringa e il dollaro ($) alla fine servono a testare se il parametro immesso (il disco e i suoi dati) è esattamente uguale a qualche altro record già inserito e non soltanto uguale a una parte di qualche record.
  Proviamo a eseguirlo inserendo un disco già registrato:
Line: 687 to 688
 disco 5^Artista9~Canzone9:Artista10~Canzone10
Changed:
<
<
     - Come vedi, il programma funziona un po' meglio ma non è ancora pronto. Man mano che ti insegnerò a programmare in shell, la nostra CDteca andrà alla grande.
>
>
     - Come vedi, il programma funziona un po' meglio ma non è ancora pronto. Man mano che ti insegnerò a programmare in shell, la nostra CDteca funzionerà sempre meglio.
 
Changed:
<
<
     - Ho capito tutto quello che mi hai spiegato, ma non so ancora come usare if per testare condizioni, cioè l'uso normale del comando.
>
>
     - Ho capito tutto ciò che mi hai spiegato, ma non so ancora come usare if per testare condizioni, cioè l'uso normale del comando.
       - Per fare quello che dici esiste il comando test, è lui a testare le condizioni. Il comando if testa il comando test. Ma il discorso è un po' confuso e, dato che ho già parlato abbastanza, ho bisogno di qualche birretta per bagnarmi la gola. Per oggi ci fermiamo qui, la prossima volta ti spiego per bene l'uso di test e di diverse altre sintassi di if.

Revision 530 Jan 2013 - AlbertoTaddei

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

Line: 435 to 435
 Ciò si è verificato perché l' ftp è stato fatto in modo binario (o image), cioè senza interpretazione del testo. Se prima della trasmissione del file fosse stata stabilita l'opzione ascii dell' ftp, tutto questo non si sarebbe verificato.
Changed:
<
<
     - Dopo queste dritte inizio questa Shell inizia quasi a piacermi, ma ci sono ancora un sacco di cose che non so fare.
>
>
     - Dopo queste dritte la Shell inizia quasi a piacermi, ma ci sono ancora un sacco di cose che non so fare.
       - È vero, finora non ti ho detto quasi niente sulla programmazione Shell e hai ancora molto da imparare, ma quello che sai è sufficiente per risolvere molti problemi una volta acquisito il “modo Shell di pensare”. Saresti capace di buttare giù uno script per dirmi chi sono le persone “loggate” da più di un giorno sul tuo server?

     - Certo che no! Per farlo dovrei conoscere i comandi condizionali che ancora non mi hai spiegato come funzionano.

Changed:
<
<
    - Lasciami provare a cambiare il tuo modo di ragionare e di avvicinarlo al “modo Shell di pensare”, ma prima è meglio farsi una bella birra alla spina... Cameriere, un altro giro...
>
>
    - Lasciami provare a cambiare il tuo modo di ragionare e di avvicinarlo al “modo Shell di pensare”, ma prima è meglio farsi una bella birra alla spina... Chico, un altro giro...
       - Adesso che mi sono bagnato l'ugola vediamo di risolvere il problema che ti ho proposto. Presta attenzione a come funziona il comando who:
Line: 697 to 697
       - Per fare il punto di quel che hai imparato prova a buttare giù un piccolo script per determinare se un certo utente, che sarà inserito come parametro, è loggato (arghh!) oppure no.
Deleted:
<
<
     - Cameriere, altre due birre alla spina per favore...

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!

 \ No newline at end of file
Added:
>
>
     - Chico, altre due birre alla spina per favore...

Revision 402 May 2012 - JulioNeves

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

Line: 431 to 431
 
Changed:
<
<
Pinguim com placa de atenção
>
>
Penguin con un piatto di attenzione
 Ciò si è verificato perché l' ftp è stato fatto in modo binario (o image), cioè senza interpretazione del testo. Se prima della trasmissione del file fosse stata stabilita l'opzione ascii dell' ftp, tutto questo non si sarebbe verificato.
Changed:
<
<
>
>
       - Dopo queste dritte inizio questa Shell inizia quasi a piacermi, ma ci sono ancora un sacco di cose che non so fare.

Revision 328 Apr 2012 - AlbertoTaddei

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

Line: 7 to 7
      - Cameriere, due birre alla spina per favore, oggi ho un sacco di cose da spiegare.
Changed:
<
<

Trabalhando com cadeias

>
>

Lavorare con le stringhe

 
Changed:
<
<
Pelo título acima não pense você que vou lhe ensinar a ser carcereiro! Estou me referindo a cadeia de caracteres!
>
>
Non pensare che il titolo voglia dire che ti insegnerò a fare il calzolaio! Mi riferisco alle stringhe di caratteri!
 
Changed:
<
<

O Comando cut (que não é a central de trabalhadores)
<--pula duas linhas-->

>
>

Il Comando cut
<--pula duas linhas-->

 
Changed:
<
<
Primeiro quero te mostrar, de forma eminentemente prática uma instrução simples de usar e muito útil: o comando cut, Esta instrução é usada para cortar um determinado pedaço de um arquivo e tem duas formas distintas de uso
>
>
Per prima cosa, ti voglio illustrare in modo pratico un'istruzione semplice da usare e molto utile: il comando cut. Questa istruzione è impiegata per tagliare una parte definita di un file e si usa in due modi diversi.
 
Changed:
<
<

O comando cut com a opção -c

>
>

Il comando cut con l'opzione -c

 
Changed:
<
<
Com esta opção, o comando tem a seguinte sintaxe:
>
>
Con questa opzione, il comando ha la seguente sintassi:
 
Changed:
<
<
     cut -c PosIni?-PosFim [arquivo]
>
>
     cut -c PosIni?-PosFin [arquivo]
 
Changed:
<
<
Onde:
>
>
Dove:
 
Changed:
<
<
     PosIni = Posição inicial
     PosFim = Posição final
>
>
     PosIni = Posizione iniziale
     PosFin = Posizione finale
 

Changed:
<
<
$ cat numeros
>
>
$ cat numeri
 1234567890 0987654321 1234554321 9876556789
Changed:
<
<
$ cut -c1-5 numeros
>
>
$ cut -c1-5 numeri
 12345 09876 12345 98765
Changed:
<
<
$ cut -c-6 numeros
>
>
$ cut -c-6 numeri
 123456 098765 123455 987655
Changed:
<
<
$ cut -c4- numeros
>
>
$ cut -c4- numeri
 4567890 7654321 4554321 6556789
Changed:
<
<
$ cut -c1,3,5,7,9 numeros
>
>
$ cut -c1,3,5,7,9 numeri
 13579 08642 13542 97568
Changed:
<
<
$ cut -c -3,5,8- numeros
>
>
$ cut -c -3,5,8- numeri
 1235890 0986321 1235321 9875789
Changed:
<
<
Como dá para ver, no duro mesmo existem quatro sintaxes distintas: na primeira (-c 1-5), eu especifiquei uma faixa, na segunda (-c -6), especifiquei tudo até uma posição, na terceira (-c 4-) de uma determinada posição em diante e na quarta (-c 1,3,5,7,9), determinadas posições. A última (-c -3,5,8-) foi só para mostrar que podemos misturar tudo.
>
>
Come si vede, ci sono quattro sintassi distinte: nella prima (-c 1-5), ho specificato un intervallo, nella seconda (-c -6), ho specificato tutto fino a una certa posizione, nella terza (-c 4-) da una determinata posizione in poi e nella quarta (-c 1,3,5,7,9), determinate posizioni. L'ultima (-c -3,5,8-) è soltanto per farti vedere che possiamo mescolarle.
 
Changed:
<
<

O comando cut com a opção -f

>
>

Il comando cut con l'opzione -f

 
Changed:
<
<
Mas não pense você que acabou por aí! Como você deve ter percebido esta forma de cut é útil para arquivos com campos de tamanho fixo, mas atualmente o que mais existe são arquivos com campos de tamanho variáveis, onde cada campo termina com um delimitador. Vamos dar uma olhada no arquivo musicas que começamos a preparar no nosso papo na última vez que viemos aqui no botequim.
>
>
Non pensare che sia tutto qui! Come avrai capito, questa forma di cut è utile quanto si maneggiano file con campi a grandezza fissa, ma nella realtà si hanno di solito file con campi a grandezza variabile ognuno dei quali termina con un delimitatore. Diamo un'occhiata al file canzoni che abbiamo iniziato a metter in piedi l'ultima volta che abbiamo fatto due chiacchiere qui al bar.
 
Changed:
<
<
$ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8
>
>
$ cat canzoni disco 1^Artista1~Canzone1:Artista2~Canzone2 disco 2^Artista3~Canzone3:Artista4~Canzone4 disco 3^Artista5~Canzone5:Artista6~Canzone5 disco 4^Artista7~Canzone7:Artista8~Canzone8
 
Changed:
<
<
Então, recapitulando, o seu "leiaute" é o seguinte:
>
>
Quindi, ricapitolando, il suo "leiaut" è il seguente:
 
Changed:
<
<
     nome do album^interprete1~nome da musica1:...:interpreten~nome da musican
>
>
     titolo del disco^interprete1~titolo della canzone1:...:interpreten~titolo della canzonen
 
Changed:
<
<
isto é, o nome do álbum será separado por um circunflexo (^) do resto do registro, que é formado por diversos grupos compostos pelo intérprete de cada música do CD e a respectiva música interpretada. Estes grupos são separados entre si por dois-pontos (:) e internamente, o nome do intérprete será separado por um til (~) do nome da música.
>
>
cioè il titolo del disco sarà separato con un accento circonflesso (^) dal resto del registro, il quale è costituito da diversi gruppi composti dall'interprete di ogni canzone del CD e la rispettiva canzone interpretata. Questi gruppi sono separati l'uno dall'altro con i due-punti (:) e, al loro interno, il nome dell'interprete sarà separato dal titolo della canzone con una tilde (~).
 
Changed:
<
<
Então para pegarmos os dados referentes a todas as segundas músicas do arquivo musicas, devemos fazer:
>
>
Detto questo, per selezionare i dati riferiti a tutte le seconde canzoni del file canzoni, dobbiamo digitare:
 
Changed:
<
<
$ cut -f2 -d: musicas Artista2~Musica2 Artista4~Musica4 Artista6~Musica5 Artista8~Musica8
>
>
$ cut -f2 -d: canzoni Artista2~Canzone2 Artista4~Canzone4 Artista6~Canzone5 Artista8~Canzone8
 
Changed:
<
<
Ou seja, cortamos o segundo campo (-f de field em inglês) delimitado (-d) por dois-pontos (:). Mas, se quisermos somente os intérpretes, devemos fazer:
>
>
Cioè, ritagliamo il secondo campo (-f dall'inglese field) delimitato (-d) dai due-punti (:). Ma, se vogliamo solamente gli interpreti, dobbiamo digitare:
 
Changed:
<
<
$ cut -f2 -d: musicas | cut -f1 -d~
>
>
$ cut -f2 -d: canzoni | cut -f1 -d~
 Artista2 Artista4 Artista6 Artista8
Changed:
<
<
Para entender isso, vamos pegar a primeira linha de musicas:
>
>
Per capire meglio, prendiamo la prima riga di canzoni:
 
Changed:
<
<
$ head -1 musicas album 1^Artista1~Musica1:Artista2~Musica2
>
>
$ head -1 canzoni disco 1^Artista1~Canzone1:Artista2~Canzone2
 
Changed:
<
<
Então observe o que foi feito:
>
>
Quindi osserva ciò che abbiamo fatto.
 
Changed:
<
<
Delimitador do primeiro cut (:)
>
>
Delimitatore del primo cut (:)
 
Changed:
<
<
     album 1^Artista1~Musica1:Artista2~Musica2
>
>
     disco 1^Artista1~Canzone1:Artista2~Canzone2
 
Changed:
<
<
Desta forma, no primeiro cut, o primeiro campo do delimitador (-d) dois-pontos (:) é album 1^Artista1~Musica1 e o segundo, que é o que nos interessa, é Artista2~Musica2.
>
>
In questo modo, nel primo cut, il primo campo del delimitatore (-d) due-punti (:) è disco 1^Artista1~Canzone1 e il secondo, che è o quello che ci in interessa, è Artista2~Canzone2.
 
Changed:
<
<
Vamos então ver o que aconteceu no segundo cut:
>
>
Vediamo allora cosa succede con il secondo cut:
 
Changed:
<
<
Novo delimitador (~)
>
>
Nuovo delimitatore (~)
 
Changed:
<
<
     Artista2~Musica2
>
>
     Artista2~Canzone2
 
Changed:
<
<
Agora, primeiro campo do delimitador (-d) til (~), que é o que nos interessa, é Artista2 e o segundo é Musica2.
>
>
Adesso, il primo campo del delimitatore (-d) tilde (~), che è quello che ci interessa, è Artista2 e il secondo è Canzone2.
 
Changed:
<
<
Se o raciocínio que fizemos para a primeira linha for aplicado no restante do arquivo, chegaremos à resposta anteriormente dada.
>
>
Se applicheremo al resto del file il ragionamento fatto per la prima riga, arriveremo alla risposta data in precedenza.
 
Changed:
<
<

Se tem cut tem paste

>
>

Se c'è cut c'è paste

 
Changed:
<
<
Como já era de se esperar, o comando paste serve para colar, só que aqui no Shell o que ele cola são arquivos. Só para começar a entendê-lo, vamos fazer assim::
>
>
Come potevamo aspettarci, il comando paste serve per incollare, solo che nella Shell ciò che si incolla sono file. Per iniziare a capire come funziona, digitiamo:
 
Changed:
<
<
paste arq1 arq2
>
>
paste file1 file2
 
Changed:
<
<
Desta forma ele mandará para a saída padrão (stdout) cada um dos registros de arq1 ao lado dos registros de arq2 correspondentes e caso nenhum delimitador seja especificado, ele usará por default o <TAB>.
>
>
In questo modo, il comando invierà allo Standard Output (stdout) tutti i record di file1 accanto a quelli corrispondenti di file2 e nel caso in cui non sia specificato alcun delimitatore, esso userà per default <TAB>.
 
Changed:
<
<
O paste é um comando pouco usado por sua sintaxe ser pouco conhecida. Vamos brincar com 2 arquivos criados da seguinte forma:
>
>
Il comando paste non è molto usato perché la sua sintassi è poco conosciuta. Proviamo a giocare con 2 file generati in questo modo:
 
Changed:
<
<
$ seq 10 > inteiros $ seq 2 2 10 > pares
>
>
$ seq 10 > interi $ seq 2 2 10 > pari
 
Changed:
<
<
Para ver o conteúdo dos arquivos criados, vamos usar o paste na sua forma careta que mostramos acima:
>
>
Per vedere il contenuto dei file generati, usiamo paste nella forma che abbiamo illustrato prima:
 
Changed:
<
<
$ paste inteiros pares
>
>
$ paste interi pari
 1 2 2 4 3 6
Line: 161 to 161
 10
Changed:
<
<

Quem está em pé, deita

>
>

Chi sta in piedi prima o poi si stende

 
Changed:
<
<
Agora vamos transformar a coluna do pares em linha:
>
>
Adesso trasformiamo la colonna dei pari nella riga:
 
Changed:
<
<
$ paste -s pares
>
>
$ paste -s pari
 2 4 6 8 10
Changed:
<
<

Usando separadores

>
>

Uso dei separatori

 
Changed:
<
<
Como já foi dito, o separador default do paste é o <TAB>, mas isso pode ser alterado com a opção -d. Então para calcular a soma do conteúdo de pares primeiramente faríamos:
>
>
Come abbiamo già detto, il separatore di default di paste è <TAB>, ma possiamo cambiarlo con l'opzione -d. Di conseguenza, per calcolare la somma del contenuto di pari digiteremo:
 
Changed:
<
<
$ paste -s -d'+' pares # também poderia ser -sd'+'
>
>
$ paste -s -d'+' pari # ma potrebbe anche essere -sd'+'
 2+4+6+8+10
Changed:
<
<
e depois passaríamos esta linha para a calculadora (bc) e então ficaria:
>
>
poi passeremo questa riga alla calcolatrice (bc), per cui otterremo:
 
Changed:
<
<
$ paste -sd'+' pares | bc
>
>
$ paste -sd'+' pari | bc
 30
Changed:
<
<
Assim sendo, para calcular o fatorial do número contido em $Num, basta:
>
>
Data questa premessa, per calcolare il fattoriale del numero contenuto in $Num, è sufficiente digitare:
 
$ seq $Num | paste -sd'*' | bc
Changed:
<
<
Com o comando paste você também pode montar formatações exóticas como esta a seguir:
>
>
Con il comando paste puoi anche generare formattazioni particolari come quella che segue:
 
$ ls | paste -s -d'\t\t\n'
Changed:
<
<
arq1 arq2 arq3 arq4 arq5 arq6
>
>
file1 file2 file3 file4 file5 file6
 
Changed:
<
<
O que aconteceu foi o seguinte: foi especificado para o comando paste que ele transformaria linhas em colunas (pela opção -s) e que os seus separadores (é...! Ele aceita mais de um, mas somente um após cada coluna criada pelo comando) seriam uma <TAB>, outra <TAB> e um <ENTER>, gerando desta forma a saída tabulada em 3 colunas.
>
>
Vediamo cos'è accaduto: è stato richiesto al comando paste di trasformare le righe in colonne (tramite l'opzione -s) e i suoi separatori (Ha ha! Il comando ne accetta più di uno, ma soltanto uno alla volta dopo ogni colonna generata dal comando stesso) sono <TAB>, poi ancora <TAB> e infine <ENTER>: ciò ha prodotto la distribuzione dei dati in 3 colonne.
 
Changed:
<
<
Agora que você já entendeu isto, veja como fazer a mesma coisa, porém de forma mais fácil e menos bizarra e tosca, usando o mesmo comando mas com a seguinte sintaxe:
>
>
Ora che hai afferrato il concetto, vediamo come fare la stessa cosa in modo più semplice e meno confuso usando lo stesso comando ma con la seguente sintassi:
 
$ ls | paste - - -
Changed:
<
<
arq1 arq2 arq3 arq4 arq5 arq6
>
>
file1 file2 file3 file4 file5 file6
 
Changed:
<
<
E isto acontece porque se ao invés de especificarmos os arquivos colocarmos o sinal de menos (-), o comando paste os substitui pela saída ou entrada padrão conforme o caso. No exemplo anterior os dados foram mandados para a saída padrão (stdout), porque o pipe (|) estava desviando a saída do ls para a entrada padrão (stdin) do paste, mas veja o exemplo a seguir:
>
>
Questo risultato si ottiene perché, inserendo i segni meno(-) invece di specificare i file, il comando paste li sostituisce con lo Standard Output o lo Standard Input a seconda del caso. Nell'esempio precedente, i dati sono stati inviati allo Standard Output (stdout) poiché la pipe (|) redireziona l'output di ls allo Standard Input (stdin) di paste, ma dai un'occhiata all'esempio seguente:
 
Changed:
<
<
$ cat arq1 predisposição privilegiado profissional $ cat arq2 encher mário motor $ cut -c-3 arq1 | paste -d "" - arq2 preencher primário promotor
>
>
$ cat file1 predisposizione privilegiato professionale $ cat file2 disporre mario motore $ cut -c-3 file1 | paste -d "" - file2 predisporre primario promotore
 
Changed:
<
<
Neste caso, o cut devolveu as três primeiras letras de cada registro de arq1, o paste foi montado para não ter separador (-d"") e receber a entrada padrão (desviada pelo pipe) no traço (-) gerando a saída juntamente com arq2.
>
>
In questo caso, cut ha restituito le prime tre lettere di ogni record di file1 e paste è stato impostato senza separatore (-d"") per ricevere lo Standard Input (redirezionato dalla pipe) al posto del trattino (-) generando un output insieme a file2.
 
Changed:
<
<

O Comando tr

>
>

Il Comando tr

 
Changed:
<
<
Outro comando muito interessante é o tr que serve para substituir, comprimir ou remover caracteres. Sua sintaxe segue o seguinte padrão:
>
>
Un altro comando molto interessante è o tr il quale serve per sostituire, comprimere o rimuovere caratteri. La sua sintassi segue lo schema sottoindicato:
 
Changed:
<
<
tr [opções] cadeia1 [cadeia2]
>
>
tr [opzioni] stringa1 [stringa2]
 
Changed:
<
<
O comando tr copia o texto da entrada padrão (stdin), troca as ocorrência dos caracteres de cadeia1 pelo seu correspondente na cadeia2 ou troca múltiplas ocorrências dos caracteres de cadeia1 por somente um caracter, ou ainda remove caracteres da cadeia1.
>
>
Il comando tr copia il testo dello Standard Input (stdin), sostituisce le occorrenze dei caratteri di stringa1 con i suoi corrispondenti di stringa2 o sostituisce occorrenze multiple di caratteri di stringa1 con un solo carattere, oppure rimuove caratteri da stringa1.
 
Changed:
<
<
As principais opções do comando são:
>
>
Le principali opzioni del comando sono:
 
Changed:
<
<
Principais Opções do comando tr
-d   Remove os caracteres de cadeia1  
  Opção     Significado  
-s   Comprime n ocorrências de cadeia1 em apenas uma  
>
>
Principali Opzioni del comando tr
-d   Rimuove i caratteri di stringa1  
  Opzione     Significato  
-s   Comprime n occorrenze di stringa1 in una soltanto  
 
Changed:
<
<

Trocando caracteres com tr

>
>

Sostituire caratteri con tr

 
Changed:
<
<
Primeiro vou te dar um exemplo bem bobo:
>
>
Per prima cosa ti farò un esempio un po' tonto:
 
Changed:
<
<
$ echo bobo | tr o a baba
>
>
$ echo tonto | tr o a tanta
 
Changed:
<
<
Isto é, troquei todas as ocorrências da letra o pela letra a.
>
>
Non ho fatto altro che sostituire tutte le occorrenze della lettera o con la lettera a.
 
Changed:
<
<
Suponha que em um determinado ponto do meu script eu peça ao operador para teclar s ou n (sim ou não), e guardo sua resposta na variável $Resp. Ora o conteúdo de $Resp pode estar com letra maiúscula ou minúscula, e desta forma eu teria que fazer diversos testes para saber se a resposta dada foi S, s, N ou n. Então o melhor é fazer:
>
>
Poniamo che in un determinato punto del mio script chieda all'operatore di digitare s o n (sì o no) e che la risposta sia immagazzinata nella variabile $Risp. Il contenuto di $Risp può essere maiuscolo o minuscolo, per cui dovrei fare diversi test per sapere se la risposta è S, s, N oppure n. La cosa migliore da fare è digitare:
 
Changed:
<
<
$ Resp=$(echo $Resp | tr SN sn)
>
>
$ Risp=$(echo $Risp | tr SN sn)
 
Changed:
<
<
e após este comando eu teria certeza que o conteúdo de $Resp seria um s ou um n.
>
>
A questo punto ho la certezza che il contenuto di $Risp è s oppure n.
 
Changed:
<
<
Se o meu arquivo ArqEnt está todo escrito com letras maiúsculas e desejo passá-las para minúsculas eu faço:
>
>
Se il mio file FileEnt è tutto in maiuscolo e voglio trasformarlo in minuscolo digiterò
 
Changed:
<
<
$ tr A-Z a-z < ArqEnt? > /tmp/$$ $ mv -f /tmp/$$ ArqEnt?
>
>
$ tr A-Z a-z < FileEnt? > /tmp/$$ $ mv -f /tmp/$$ FileEnt?
 
Changed:
<
<
Note que neste caso usei a notação A-Z para não escrever ABCD...YZ. Outro tipo de notação que pode ser usada são as escape sequences (prefiro escrever no bom e velho português, mas nesse caso como eu traduziria? Seqüências de escape? Meio sem sentido, né? Mas vá lá...) que também são reconhecidas por outros comandos e também na linguagem C, e cujo significado você verá a seguir:
>
>
Osserva che ho usato la notazione A-Z per non scrivere ABCD...YZ. Un altro tipo di notazione che può essere usata sono le cosiddette sequenze di escape (in inglese escape sequences), riconosciute anche da altri comandi e nel linguaggio C. Vedremo il loro significato più avanti:
 
Escape Sequences
Changed:
<
<
\\   Uma barra invertida   \0134
  Seqüência     Significado     Octal  
\t   Tabulação   \011
\n   Nova linha   \012
\v   Tabulação Vertical   \013
\f   Nova Página   \014
\r   Início da linha <^M>   \015
>
>
\\   Una barra rovesciata   \0134
  Sequenza     Significato     Ottale  
\t   Tabulazione   \011
\n   Nuova riga   \012
\v   Tabulazione Verticale   \013
\f   Nuova Pagina   \014
\r   Inizio della riga <^M>   \015
 
Changed:
<
<

Removendo caracteres com tr

>
>

Rimuovere caratteri con tr

 
Changed:
<
<
Então deixa eu te contar um "causo": um aluno que estava danado comigo, resolveu complicar a minha vida e em um exercício prático valendo nota que passei para ser feito no computador, me entregou o script com todos os comandos separados por ponto-e-vírgula (lembra que eu disse que o ponto-e-vírgula servia para separar diversos comandos em uma mesma linha?).
>
>
Lascia che ti racconti un aneddoto: un alunno che ce l'aveva con me decise di complicarmi la vita e, in un esercizio pratico con tanto di voto che avevo dato da fare al computer, mi consegnò uno script con tutti i comandi separati da un punto-e-virgola (ricordi che ti ho detto che il punto-e-virgola serve per separare diversi comandi in una stessa riga?).
 
Changed:
<
<
Vou dar um exemplo simplificado e idiota de uma "tripa" assim:
>
>
Eccoti un esempio facile facile di una roba del genere:
 
$ cat confuso
Changed:
<
<
echo leia Programação Shell Linux do Julio Cezar Neves > livro;cat livro;pwd;ls;rm -f lixo 2>/dev/null;cd ~
>
>
echo leggi Programmazione Shell Linux di Julio Cezar Neves > libro;cat libro;pwd;ls;rm -f robaccia 2>/dev/null;cd ~
 
Changed:
<
<
Eu executava o programa e ele funcionava:
>
>
Io eseguivo il programma e quello funzionava così:
 
$ confuso
Changed:
<
<
leia Programação Shell Linux do Julio Cezar Neves
>
>
leggi Programmazione Shell Linux di Julio Cezar Neves
 /home/jneves/LM
Changed:
<
<
confuso livro musexc musicas musinc muslist numeros
>
>
confuso livro elimcanz canzoni insercanz listcanz numeri
 
Changed:
<
<
Mas nota de prova é coisa séria (e nota de dólar é mais ainda :)) então, para entender o que o aluno havia feito, o chamei e em sua frente executei o seguinte comando:
>
>
Ma il voto è una cosa seria quindi, per capire ciò che l'alunno aveva fatto, lo chiamai e davanti ai suoi occhi digitai il seguente comando:
 
$ tr ";" "\n" < confuso
Changed:
<
<
echo leia Programação Shell Linux do Julio Cezar Neves
>
>
echo leggi Programmazione Shell Linux do Julio Cezar Neves
 pwd ls rm -f lixo 2>/dev/null cd ~
Changed:
<
<
O cara ficou muito desapontado, porque em 2 ou 3 segundos eu desfiz a gozação que ele perdera horas para fazer.
>
>
Il tizio ci restò male perché in 2 o 3 secondi smontai il bello scherzo per mettere su il quale aveva sprecato tanto tempo.
 
Changed:
<
<
Mas preste atenção! Se eu estivesse em uma máquina com Unix, eu teria feito:
>
>
Ma attento! Se avessi avuto una macchina con Unix avrei dovuto digitare:
 
$ tr ";" "\012" < confuso
Changed:
<
<

Xpremendo com tr

>
>

Espressioni con tr

 
Changed:
<
<
Agora veja a diferença entre os dois comandos date: o que fiz hoje e outro que foi executado há duas semanas:
>
>
Vediamo adesso la differenza tra due comandi date: ciò che ho fatto oggi e ciò che ho fatto due settimane fa:
 
Changed:
<
<
$ date # Hoje
>
>
$ date # Oggi
 Sun Sep 19 14:59:54 2004
Changed:
<
<
$ date # Há duas semanas
>
>
$ date # Due settimane fa
 Sun Sep 5 10:12:33 2004
Changed:
<
<
Para pegar a hora eu deveria fazer:
>
>
Per incollare l'ora dovrei digitare:
 
$ date | cut -f 4 -d ' ' 14:59:54
Changed:
<
<
Mas duas semanas antes ocorreria o seguinte:
>
>
Ma due settimane fa avrei ottenuto questo:
 
$ date | cut -f 4 -d ' ' 5
Changed:
<
<
Mas observe porque:
>
>
Osserva bene il perché:
 
Changed:
<
<
$ date # Há duas semanas
>
>
$ date # Due settimane fa
 Sun Sep 5 10:12:33 2004
Changed:
<
<
Como você pode notar, existem 2 caracteres em branco antes do 5 (dia), o que estraga tudo porque o terceiro pedaço está vazio e o quarto é o dia (5). Então o ideal seria comprimir os espaços em brancos sucessivos em somente um espaço para poder tratar as duas cadeias resultantes do comando date da mesma forma, e isso se faz assim:
>
>
Come puoi notare, ci sono 2 spazi prima di 5 (giorno), cosa che rovina tutto perché il terzo pezzo è vuoto e il quarto è il giorno (5). L'ideale sarebbe comprimere gli spazi in sequenza in uno soltanto per trattare le due stringhe risultanti dal comando date allo stesso modo, e questo si ottiene digitando:
 
$ date | tr -s " " Sun Sep 5 10:12:33 2004
Changed:
<
<
Como você pode ver não existem mais os dois espaços, então agora eu poderia cortar:
>
>
Come puoi vedere non ci sono più i due spazi, per cui posso abbreviare:
 
$ date | tr -s " " | cut -f 4 -d " " 10:12:33
Changed:
<
<
Olha só como o Shell já está quebrando o galho. Veja este arquivo que foi baixado de uma máquina com aquele sistema operacional que pega vírus:
>
>
Guarda come la Shell risolve i problemi. Da' un'occhiata a questo file scaricato da una macchina che ha quel sistema operativo che si becca i virus:
 
Changed:
<
<
$ cat -ve ArqDoDOS?.txt Este arquivo^M$ foi gerado pelo^M$ DOS/Rwin e foi^M$ baixado por um^M$ ftp mal feito.^M$
>
>
$ cat -ve FileDiDOS?.txt Questo file^M$ è stato generato da^M$ DOS/Rwin ed è stato^M$ scaricato da un^M$ ftp mal fatto.^M$
 
Changed:
<
<
E agora eu quero te dar duas dicas:
>
>
Adesso voglio darti due dritte:
 
Changed:
<
<
Pinguim com placa de dica Dica #1 - A opção -v do cat mostra os caracteres de controle invisíveis, com a notação ^L, onde ^ é a tecla control e L é a respectiva letra. A opção -e mostra o final da linha como um cifrão ($).
>
>
Pinguim com placa de dica (em inglês) Tip #1 - L'opzione -v di cat mostra i caratteri di controllo invisibili con la notazione ^L, nella quale ^ è il tasto control e L è la rispettiva lettera. L'opzione -e mostra la fine della riga come un dollaro ($).
 
Changed:
<
<
Pinguim com placa de dica Dica #2 - Isto ocorre porque no formato DOS (ou rwin), o fim dos registros é formado por um carriage-return (\r) e um line-feed (\n). No Linux porém o final do registro tem somente o line-feed.
>
>
Pinguim com placa de dica (em inglês) Tip #2 - Ciò accade perché nel DOS (ou rwin) la fine dei record è costituita da un carriage-return (\r) e un line-feed (\n). In Linux la fine del record ha soltanto il line-feed.
 
Changed:
<
<
Vamos então limpar este arquivo.
>
>
Adesso facciamo un po' di pulizia dentro al file.
 
Changed:
<
<
$ tr -d '\r' < ArqDoDOS?.txt > /tmp/$$ $ mv -f /tmp/$$ ArqDoDOS?.txt
>
>
$ tr -d '\r' < FileDiDOS?.txt > /tmp/$$ $ mv -f /tmp/$$ FileDiDOS?.txt
 
Changed:
<
<
Agora vamos ver o que aconteceu:
>
>
e vediamo cosa succede:
 
Changed:
<
<
$ cat -ve ArqDoDOS?.txt Este arquivo$ foi gerado pelo$ DOS/Rwin e foi$ baixado por um$ ftp mal feito.$
>
>
$ cat -ve FileDiDOS?.txt Questo file$ è stato generato da$ DOS/Rwin ed è stato$ scaricato da un$ ftp mal fatto.$
 
Changed:
<
<
Bem a opção -d do tr remove o caractere especificado de todo o arquivo. Desta forma eu removi os caracteres indesejados salvando em um arquivo de trabalho e posteriormente renomeei-o para a sua designação original.
>
>
L'opzione -d di tr rimuove il carattere specificato dall'intero file. In questo modo ho rimosso i caratteri indesiderati salvando il contenuto in un file di lavoro e ho poi rinominato lo stesso con il suo nome originale.
 
Changed:
<
<
Obs: No Unix eu deveria fazer:
>
>
Nota: In Unix avrei dovuto digitare:
 
Changed:
<
<
$ tr -d '\015' < ArqDoDOS?.txt > /tmp/$$
>
>
$ tr -d '\015' < FileDiDOS?.txt > /tmp/$$
 

Pinguim com placa de atenção
Changed:
<
<
Isto aconteceu porque o ftp foi feito do modo binário (ou image), isto é, sem a interpretação do texto. Se antes da transmissão do arquivo tivesse sido estipulada a opção ascii do ftp, isto não teria ocorrido.
>
>
Ciò si è verificato perché l' ftp è stato fatto in modo binario (o image), cioè senza interpretazione del testo. Se prima della trasmissione del file fosse stata stabilita l'opzione ascii dell' ftp, tutto questo non si sarebbe verificato.
 
Changed:
<
<
     - Olha, depois desta dica tô começando a gostar deste tal de Shell, mas ainda tem muita coisa que não consigo fazer.
>
>
     - Dopo queste dritte inizio questa Shell inizia quasi a piacermi, ma ci sono ancora un sacco di cose che non so fare.
 
Changed:
<
<
     - Pois é, ainda não te falei quase nada sobre programação em Shell, ainda tem muita coisa para aprender, mas com o que aprendeu, já dá para resolver muitos problemas, desde que você adquira o “modo Shell de pensar”. Você seria capaz de fazer um script para me dizer quais são as pessoas que estão “logadas” há mais de um dia no seu servidor?
>
>
     - È vero, finora non ti ho detto quasi niente sulla programmazione Shell e hai ancora molto da imparare, ma quello che sai è sufficiente per risolvere molti problemi una volta acquisito il “modo Shell di pensare”. Saresti capace di buttare giù uno script per dirmi chi sono le persone “loggate” da più di un giorno sul tuo server?
 
Changed:
<
<
     - Claro que não! Para isso seria necessário eu conhecer os comandos condicionais que você ainda não me explicou como funcionam.
>
>
     - Certo che no! Per farlo dovrei conoscere i comandi condizionali che ancora non mi hai spiegato come funzionano.
 
Changed:
<
<
    - Deixa eu tentar mudar um pouco a sua lógica e trazê-la para o “modo Shell de pensar”, mas antes é melhor tomarmos um chope... Ô Chico, traz mais dois...
>
>
    - Lasciami provare a cambiare il tuo modo di ragionare e di avvicinarlo al “modo Shell di pensare”, ma prima è meglio farsi una bella birra alla spina... Cameriere, un altro giro...
 
Changed:
<
<
     - Agora que já molhei a palavra, vamos resolver o problema que te propus. Repare como funciona o comando who:
>
>
     - Adesso che mi sono bagnato l'ugola vediamo di risolvere il problema che ti ho proposto. Presta attenzione a come funziona il comando who:
 
$ who
Line: 453 to 453
 lcarlos pts/3 Sep 20 10:01
Changed:
<
<
E veja também o date:
>
>
Dai uno sguardo anche a date:
 
$ date Mon Sep 20 10:47:19 BRT 2004
Changed:
<
<
Repare que o mês e o dia estão no mesmo formato em ambos os comandos.
>
>
Nota che il mese e l'anno si presentano nello stesso formato in entrambi i comandi.
 
Changed:
<
<
Pinguim com placa de dica Algumas vezes um comando tem a saída em português e o outro em inglês. Quando isso ocorrer, você pode usar o seguinte artifício:
>
>
Pinguim com placa de dica (em inglês) A volte il comando restituisce un output in italiano, altre volte in inglese. Quando ciò si verifica puoi usare questo trucco:
 
$ date Mon Sep 20 10:47:19 BRT 2004
Changed:
<
<
$ LANG=pt_BR date Seg Set 20 10:47:19 BRT 2004
>
>
$ LANG=it_IT date Lun Set 20 10:47:19 BRT 2004
 
Changed:
<
<
Desta forma passando a saída do comando date para português.
>
>
In questo modo l'output del comando date è in italiano.
 
Changed:
<
<
Ora, se em algum registro do who eu não encontrar a data de hoje, é sinal que o cara está "logado" há mais de um dia, já que ele não pode ter se "logado" amanhã... Então vamos guardar o pedaço que importa da data de hoje para procurá-la na saída do who:
>
>
Detto questo, se non trovo la data di oggi in nessun record di who, ciò significa che la persona è "loggata" da più di un giorno poiché non può essersi “loggato” domani... Memorizziamo la parte che ci interessa della data di oggi per cercarla nell'output di who:
 
$ Data=$(date | cut -c 5-10)
Changed:
<
<
Eu usei a construção $(...), para priorizar a execução dos comandos antes de atribuir a sua saída à variável $Data. Vamos ver se funcionou:
>
>
Ho usato il costrutto $(...), per rendere prioritaria l'esecuzione dei comandi prima di attribuire il loro output alla variabile $Data. Vediamo se funziona:
 
$ echo $Data Sep 20
Changed:
<
<
Beleza! Agora, o que temos que fazer é procurar no comando who os registros que não possuem esta data.
>
>
Una meraviglia! Adesso non ci resta che cercare i record del comando who che non hanno quella data.
 
Changed:
<
<
     - Ah! Eu acho que estou entendendo! Você falou em procurar e me ocorreu o comando grep, estou certo?
>
>
     - Ah! Credo di aver capito! Hai detto cercare e mi è venuto in mente il comando grep, giusto?
 
Changed:
<
<
     - Certíssimo! Só que eu tenho que usar o grep com aquela opção que ele só lista os registros nos quais ele não encontrou a cadeia. Você se lembra que opção é essa?
>
>
     - Giustissimo! Solo che devo usare grep con l'opzione che mi permette di elencare i record nei quali non ha trovato la stringa. Ricordi di quale opzione si tratta?
 
Changed:
<
<
     - Claro, é a opção -v...
>
>
     - Certo, è l'opzione -v...
 
Changed:
<
<
     - Isso! Tá ficando bão! Então vamos ver:
>
>
     - Proprio lei! Allora stai imparando! Vediamo:
 
$ who | grep -v "$Data" jneves pts/1 Sep 18 13:40
Changed:
<
<
     - E se eu quisesse mais um pouco de perfumaria eu faria assim:
>
>
     - E se volessi un tocco estetico digiterei:
 
$ who | grep -v "$Data" | cut -f1 -d ' ' jneves
Changed:
<
<
     - Viu? Não foi necessário usar nenhum comando condicional, até porque o nosso mais usado comando condicional, o famoso if, não testa condição, mas sim instruções, como veremos agora.
>
>
     - Visto? Non abbiamo dovuto fare uso di alcun comando condizionale perché il più utilizzato tra essi, il famoso if, non testa condizioni, ma istruzioni, come adesso ti spiegherò.
 

Changed:
<
<

Comandos Condicionais

>
>

Comandi Condizionali

 

Veja as linhas de comando a seguir:

Changed:
<
<
$ ls musicas musicas
>
>
$ ls canzoni canzoni
 $ echo $? 0
Changed:
<
<
$ ls ArqInexistente? ls: ArqInexistente?: No such file or directory
>
>
$ ls FileInesistente? ls: FileInesistente?: No such file or directory
 $ echo $? 1 $ who | grep jneves
Line: 536 to 536
 
Changed:
<
<
     - O que é esse $? faz aí? Começando por cifrão ($) parece ser uma variável, certo?
>
>
     - Cos'è quel $? lì? Dato che inizia con il dollaro ($) direi che è una variabile, giusto?
 
Changed:
<
<
     - Sim é uma variável que contém o código de retorno da última instrução executada. Posso te garantir que se esta instrução foi bem sucedida, $? terá o valor zero, caso contrário seu valor será diferente de zero.
>
>
     - Sì, è una variabile che contiene il codice di ritorno dell'ultima istruzione eseguita. Ti posso assicurare che, se l'istruzione è stata eseguita bene, $? avrà valore zero, altrimenti il suo valore sarà diverso da zero.
 
Changed:
<
<

O Comando if

>
>

Il Comando if

 
Changed:
<
<
O que o nosso comando condicional if faz é testar a variável $?. Então vamos ver a sua sintaxe:
>
>
Ciò che il nostro comando condizionale if fa è testare la variabile $?. Vediamone la sintassi:
 
    if cmd
    then
Line: 558 to 558
  fi
Changed:
<
<
ou seja: caso comando cmd tenha sido executado com sucesso, os comandos do bloco do then (cmd1, cmd2 e cmdn) serão executados, caso contrário, os comandos executados serão os do bloco opcional do else (cmd3, cmd4 e cmdm), terminando com um fi.
>
>
cioè: se il comando cmd è stato eseguito con successo, i comandi del blocco di then (cmd1, cmd2 e cmdn) saranno eseguiti, altrimenti i comandi da eseguire saranno quelli del blocco opzionale di else (cmd3, cmd4 e cmdm): iltutto termina con fi.
 
Changed:
<
<
Vamos ver na prática como isso funciona usando um scriptizinho que serve para incluir usuários no /etc/passwd:
>
>
Vediamo come tutto questo funzionabcon un piccolo script che serve a inserire gli utenti in /etc/passwd:
 
Changed:
<
<
$ cat incusu
>
>
$ cat inserutente
 #!/bin/bash
Changed:
<
<
# Versão 1
>
>
# Versione 1
 if grep ^$1 /etc/passwd then
Changed:
<
<
echo Usuario \'$1\' já existe
>
>
echo L'utente \'$1\' è già presente
 else if useradd $1 then
Changed:
<
<
echo Usuário \'$1\' incluído em /etc/passwd
>
>
echo L'utente \'$1\' è stato inserito in /etc/passwd
  else
Changed:
<
<
echo "Problemas no cadastramento. Você é root?"
>
>
echo "Problemi di inserimento. Sei root?"
  fi fi
Changed:
<
<
Repare que o if está testando direto o comando grep e esta é a sua finalidade. Caso o if seja bem sucedido, ou seja, o usuário (cujo nome está em $1) foi encontrado em /etc/passwd, os comandos do bloco do then serão executados (neste exemplo é somente o echo) e caso contrário, as instruções do bloco do else é que serão executadas, quando um novo if testa se o comando useradd foi executado a contento, criando o registro do usuário em /etc/passwd, ou não quando dará a mensagem de erro.
Vejamos sua execução, primeiramente passando um usuário já cadastrado:
>
>
Osserva che if testa direttamente il comando grep ed è questo il suo scopo. Se if ha successo, cioè se l'utente (il cui nome è in $1) è presente in /etc/passwd, saranno eseguiti i comandi del blocco di then (nel nostro esempio soltanto echo), altrimenti saranno le istruzioni del blocco di else a essere eseguite, per cui un nuovo if testerà se il comando useradd è stato eseguito come si deve e quindi genererà il record dell'utente in /etc/passwd oppure presenterà un messaggio di errore.
Vediamone l'esecuzione, inizialmente inserendo un utente già registrato:
 
Changed:
<
<
$ incusu jneves
>
>
$ inserutente jneves
 jneves:x:54002:1001:Julio Neves:/home/jneves:/bin/bash
Changed:
<
<
Usuario 'jneves' ja existe
>
>
L'utente 'jneves' è già presente
 
Changed:
<
<
Como já vimos diversas vezes, mas é sempre bom insistir no tema para que você já fique precavido, no exemplo dado surgiu uma linha indesejada, ela é a saída do comando grep. Para evitar que isso aconteça, devemos desviar a saída desta instrução para /dev/null, ficando assim:
>
>
Come abbiamo visto in precedenza, ma è sempre meglio ripetere affinché tu stia attento, nell'esempio è spuntata fuori una riga indesiderata che altro non è che l'output del comando grep. Per evitare che questo accada, dobbiamo redirigere l'output di questa istruzione in /dev/null:
 
Changed:
<
<
$ cat incusu
>
>
$ cat inserutente
 #!/bin/bash
Changed:
<
<
# Versão 2
>
>
# Versione 2
 if grep ^$1 /etc/passwd > /dev/null # ou: if grep -q ^$1 /etc/passwd then
Changed:
<
<
echo Usuario \'$1\' já existe
>
>
echo L'utente \'$1\' è già presente
 else if useradd $1 then
Changed:
<
<
echo Usuário \'$1\' incluído em /etc/passwd
>
>
echo L'utente \'$1\' è stato inserito in /etc/passwd
  else
Changed:
<
<
echo "Problemas no cadastramento. Você é root?"
>
>
echo "Problemi di inserimento. Sei root?"
  fi fi
Changed:
<
<
Agora vamos testá-lo como usuário normal (não root):
>
>
Eseguiamolo adesso come utente normale (non root):
 
Changed:
<
<
$ incusu ZeNinguem? ./incusu[6]: useradd: not found Problemas no cadastramento. Você é root?
>
>
$ inserutente PincoPallino? ./inserutente[6]: useradd: not found Problemi di inserimento. Sei root?
 
Changed:
<
<
Epa, aquele erro não era para acontecer! Para evitar que isso aconteça devemos mandar também a saída de erro (strerr, lembra?) do useradd para /dev/null, ficando na versão final assim:
>
>
Cavoli, quell'errore non doveva uscire! Per evitarlo dobbiamo redirigere in /dev/null anche lo Standard Error (strerr, ricordi?) di useradd:
 
Changed:
<
<
$ cat incusu
>
>
$ cat inserutente
 #!/bin/bash
Changed:
<
<
# Versão 3
>
>
# Versione 3
 if grep ^$1 /etc/passwd > /dev/null then
Changed:
<
<
echo Usuario \'$1\' já existe
>
>
echo L'utente \'$1\' è già presente
 else if useradd $1 2> /dev/null then
Changed:
<
<
echo Usuário \'$1\' incluído em /etc/passwd
>
>
echo L'utente \'$1\' è stato inserito in /etc/passwd
  else
Changed:
<
<
echo "Problemas no cadastramento. Você é root?"
>
>
echo "Problemi di inserimento. Sei root?"
  fi fi
Changed:
<
<
Depois destas alterações e de fazer um su – (me tornar root) vejamos o seu comportamento:
>
>
Vediamo come si comporta una volta apportate queste modifiche e aver eseguito su – (sono diventato root):
 
Changed:
<
<
$ incusu botelho Usuário 'botelho' incluido em /etc/passwd
>
>
$ inserutente botelho L'utente 'botelho' è stato inserito in /etc/passwd
 
Changed:
<
<
E novamente:
>
>
E ancora:
 
Changed:
<
<
$ incusu botelho Usuário 'botelho' já existe
>
>
$ inserutente botelho L'utente 'botelho' è già presente
 
Changed:
<
<
Lembra que eu falei que ao longo dos nossos papos e chopes os nossos programas iriam se aprimorando? Então vejamos agora como poderíamos melhorar o nosso programa para incluir músicas:
>
>
Ricordi che ti ho detto che, tra una chiacchiera e una birra, i nostri programmi sarebbero diventati più raffinati? Vediamo come possiamo migliorare il nostro programma per registrare le canzoni:
 
Changed:
<
<
$ cat musinc
>
>
$ cat insercanz
 #!/bin/bash
Changed:
<
<
# Cadastra CDs (versao 3)
>
>
# Registra CDs (versione 3)
 #
Changed:
<
<
if grep "^$1$" musicas > /dev/null
>
>
if grep "^$1$" canzoni > /dev/null
 then
Changed:
<
<
echo Este álbum já está cadastrado
>
>
echo Questo disco è già stato registrato
 else
Changed:
<
<
echo $1 >> musicas sort musicas -o musicas
>
>
echo $1 >> canzoni sort canzoni -o canzoni
 fi
Changed:
<
<
Como você viu, é uma pequena evolução da versão anterior, assim, antes de incluir um registro (que pela versão anterior poderia ser duplicado), testamos se o registro começava (^) e terminava ($) igual ao parâmetro passado ($1). O uso do circunflexo (^) no início da cadeia e cifrão ($) no fim, são para testar se o parâmetro passado (o álbum e seus dados) são exatamente iguais a algum registro anteriormente cadastrado e não somente igual a um pedaço de algum dos registros.
>
>
Come puoi vedere si tratta di una piccola variazione della versione precedente: adesso, prima di inserire un record, (che nella versione precedente poteva essere duplicato), controlliamo se il record inizia (^) e finisce ($) allo stesso modo del parametro immesso ($1). L'accento circonflesso (^) all'inizio della stringa e il dollaro ($) alla fine servono a testare se il parametro immesso (il disco e i suoi dati) è esattamente uguale a qualche altro record già inserito e non soltanto uguale a una parte di qualche record.
 
Changed:
<
<
Vamos executá-lo passando um álbum já cadastrado:
>
>
Proviamo a eseguirlo inserendo un disco già registrato:
 
Changed:
<
<
$ musinc "album 4^Artista7~Musica7:Artista8~Musica8" Este álbum já está cadastrado
>
>
$ insercanz "disco 4^Artista7~Canzone7:Artista8~Canzone8" Questo disco è già stato registrato
 
Changed:
<
<
E agora um não cadastrado:
>
>
E adesso con uno non registrato:
 
Changed:
<
<
$ musinc "album 5^Artista9~Musica9:Artista10~Musica10" $ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8 album 5^Artista9~Musica9:Artista10~Musica10
>
>
$ insercanz "disco 5^Artista9~Canzone9:Artista10~Canzone10" $ cat canzoni disco 1^Artista1~Canzone1:Artista2~Canzone2 disco 2^Artista3~Canzone3:Artista4~Canzone4 disco 3^Artista5~Canzone5:Artista6~Canzone5 disco 4^Artista7~Canzone7:Artista8~Canzone8 disco 5^Artista9~Canzone9:Artista10~Canzone10
 
Changed:
<
<
     - Como você viu, o programa melhorou um pouquinho, mas ainda não está pronto. À medida que eu for te ensinando a programar em shell, nossa CDteca irá ficando cada vez melhor.
>
>
     - Come vedi, il programma funziona un po' meglio ma non è ancora pronto. Man mano che ti insegnerò a programmare in shell, la nostra CDteca andrà alla grande.
 
Changed:
<
<
     - Entendi tudo que você me explicou, mas ainda não sei como fazer um if para testar condições, ou seja o uso normal do comando.
>
>
     - Ho capito tutto quello che mi hai spiegato, ma non so ancora come usare if per testare condizioni, cioè l'uso normale del comando.
 
Changed:
<
<
     - Cara, para isso existe o comando test, ele é que testa condições. O comando if testa o comando test. Mas isso está meio confuso e como já falei muito, estou precisando de uns chopes para molhar a palavra. Vamos parando por aqui e na próxima vez te explico direitinho o uso do test e de diversas outras sintaxes do if.
>
>
     - Per fare quello che dici esiste il comando test, è lui a testare le condizioni. Il comando if testa il comando test. Ma il discorso è un po' confuso e, dato che ho già parlato abbastanza, ho bisogno di qualche birretta per bagnarmi la gola. Per oggi ci fermiamo qui, la prossima volta ti spiego per bene l'uso di test e di diverse altre sintassi di if.
 
Changed:
<
<
     - Falou! Acho bom mesmo porque eu também já tô ficando zonzo e assim tenho tempo para praticar esse monte de coisas que você me falou hoje.
>
>
     - Sono d'accordo! Credo anch'io che sia meglio fermarci, anche perché mi sento un po' rintronato e così ho tempo per fare pratica su tutta quella roba di cui mi hai parlato oggi.
 
Changed:
<
<
     - Para fixar o que você aprendeu, tente fazer um scriptizinho para informar se um determinado usuário, que será passado como parâmetro esta logado (arghh!) ou não.
>
>
     - Per fare il punto di quel che hai imparato prova a buttare giù un piccolo script per determinare se un certo utente, che sarà inserito come parametro, è loggato (arghh!) oppure no.
 
Changed:
<
<
     - Aê Chico, mais dois chopes por favor...
>
>
     - Cameriere, altre due birre alla spina per favore...
  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.

Revision 222 Apr 2012 - AlbertoTaddei

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

Revision 118 Apr 2012 - AlbertoTaddei

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

Chiacchiere da Bar Parte III
<--pula duas linhas-->

    - Cameriere, due birre alla spina per favore, oggi ho un sacco di cose da spiegare.

Trabalhando com cadeias

Pelo título acima não pense você que vou lhe ensinar a ser carcereiro! Estou me referindo a cadeia de caracteres!

O Comando cut (que não é a central de trabalhadores)
<--pula duas linhas-->

Primeiro quero te mostrar, de forma eminentemente prática uma instrução simples de usar e muito útil: o comando cut, Esta instrução é usada para cortar um determinado pedaço de um arquivo e tem duas formas distintas de uso

O comando cut com a opção -c

Com esta opção, o comando tem a seguinte sintaxe:

     cut -c PosIni-PosFim [arquivo]

Onde:

     PosIni = Posição inicial
     PosFim = Posição final

$ cat numeros 1234567890 0987654321 1234554321 9876556789 $ cut -c1-5 numeros 12345 09876 12345 98765 $ cut -c-6 numeros 123456 098765 123455 987655 $ cut -c4- numeros 4567890 7654321 4554321 6556789 $ cut -c1,3,5,7,9 numeros 13579 08642 13542 97568 $ cut -c -3,5,8- numeros 1235890 0986321 1235321 9875789

Como dá para ver, no duro mesmo existem quatro sintaxes distintas: na primeira (-c 1-5), eu especifiquei uma faixa, na segunda (-c -6), especifiquei tudo até uma posição, na terceira (-c 4-) de uma determinada posição em diante e na quarta (-c 1,3,5,7,9), determinadas posições. A última (-c -3,5,8-) foi só para mostrar que podemos misturar tudo.

O comando cut com a opção -f

Mas não pense você que acabou por aí! Como você deve ter percebido esta forma de cut é útil para arquivos com campos de tamanho fixo, mas atualmente o que mais existe são arquivos com campos de tamanho variáveis, onde cada campo termina com um delimitador. Vamos dar uma olhada no arquivo musicas que começamos a preparar no nosso papo na última vez que viemos aqui no botequim.

$ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8

Então, recapitulando, o seu "leiaute" é o seguinte:

     nome do album^interprete1~nome da musica1:...:interpreten~nome da musican

isto é, o nome do álbum será separado por um circunflexo (^) do resto do registro, que é formado por diversos grupos compostos pelo intérprete de cada música do CD e a respectiva música interpretada. Estes grupos são separados entre si por dois-pontos (:) e internamente, o nome do intérprete será separado por um til (~) do nome da música.

Então para pegarmos os dados referentes a todas as segundas músicas do arquivo musicas, devemos fazer:

$ cut -f2 -d: musicas Artista2~Musica2 Artista4~Musica4 Artista6~Musica5 Artista8~Musica8

Ou seja, cortamos o segundo campo (-f de field em inglês) delimitado (-d) por dois-pontos (:). Mas, se quisermos somente os intérpretes, devemos fazer:

$ cut -f2 -d: musicas | cut -f1 -d~ Artista2 Artista4 Artista6 Artista8

Para entender isso, vamos pegar a primeira linha de musicas:

$ head -1 musicas album 1^Artista1~Musica1:Artista2~Musica2

Então observe o que foi feito:

Delimitador do primeiro cut (:)

     album 1^Artista1~Musica1:Artista2~Musica2

Desta forma, no primeiro cut, o primeiro campo do delimitador (-d) dois-pontos (:) é album 1^Artista1~Musica1 e o segundo, que é o que nos interessa, é Artista2~Musica2.

Vamos então ver o que aconteceu no segundo cut:

Novo delimitador (~)

     Artista2~Musica2

Agora, primeiro campo do delimitador (-d) til (~), que é o que nos interessa, é Artista2 e o segundo é Musica2.

Se o raciocínio que fizemos para a primeira linha for aplicado no restante do arquivo, chegaremos à resposta anteriormente dada.

Se tem cut tem paste

Como já era de se esperar, o comando paste serve para colar, só que aqui no Shell o que ele cola são arquivos. Só para começar a entendê-lo, vamos fazer assim::

    paste arq1 arq2

Desta forma ele mandará para a saída padrão (stdout) cada um dos registros de arq1 ao lado dos registros de arq2 correspondentes e caso nenhum delimitador seja especificado, ele usará por default o <TAB>.

O paste é um comando pouco usado por sua sintaxe ser pouco conhecida. Vamos brincar com 2 arquivos criados da seguinte forma:

$ seq 10 > inteiros $ seq 2 2 10 > pares

Para ver o conteúdo dos arquivos criados, vamos usar o paste na sua forma careta que mostramos acima:

$ paste inteiros pares 1 2 2 4 3 6 4 8 5 10 6 7 8 9 10

Quem está em pé, deita

Agora vamos transformar a coluna do pares em linha:

$ paste -s pares 2 4 6 8 10

Usando separadores

Como já foi dito, o separador default do paste é o <TAB>, mas isso pode ser alterado com a opção -d. Então para calcular a soma do conteúdo de pares primeiramente faríamos:

$ paste -s -d'+' pares # também poderia ser -sd'+' 2+4+6+8+10

e depois passaríamos esta linha para a calculadora (bc) e então ficaria:

$ paste -sd'+' pares | bc 30

Assim sendo, para calcular o fatorial do número contido em $Num, basta:

$ seq $Num | paste -sd'*' | bc

Com o comando paste você também pode montar formatações exóticas como esta a seguir:

$ ls | paste -s -d'\t\t\n' arq1 arq2 arq3 arq4 arq5 arq6

O que aconteceu foi o seguinte: foi especificado para o comando paste que ele transformaria linhas em colunas (pela opção -s) e que os seus separadores (é...! Ele aceita mais de um, mas somente um após cada coluna criada pelo comando) seriam uma <TAB>, outra <TAB> e um <ENTER>, gerando desta forma a saída tabulada em 3 colunas.

Agora que você já entendeu isto, veja como fazer a mesma coisa, porém de forma mais fácil e menos bizarra e tosca, usando o mesmo comando mas com a seguinte sintaxe:

$ ls | paste - - - arq1 arq2 arq3 arq4 arq5 arq6

E isto acontece porque se ao invés de especificarmos os arquivos colocarmos o sinal de menos (-), o comando paste os substitui pela saída ou entrada padrão conforme o caso. No exemplo anterior os dados foram mandados para a saída padrão (stdout), porque o pipe (|) estava desviando a saída do ls para a entrada padrão (stdin) do paste, mas veja o exemplo a seguir:

$ cat arq1 predisposição privilegiado profissional $ cat arq2 encher mário motor $ cut -c-3 arq1 | paste -d "" - arq2 preencher primário promotor

Neste caso, o cut devolveu as três primeiras letras de cada registro de arq1, o paste foi montado para não ter separador (-d"") e receber a entrada padrão (desviada pelo pipe) no traço (-) gerando a saída juntamente com arq2.

O Comando tr

Outro comando muito interessante é o tr que serve para substituir, comprimir ou remover caracteres. Sua sintaxe segue o seguinte padrão:

    tr [opções] cadeia1 [cadeia2]

O comando tr copia o texto da entrada padrão (stdin), troca as ocorrência dos caracteres de cadeia1 pelo seu correspondente na cadeia2 ou troca múltiplas ocorrências dos caracteres de cadeia1 por somente um caracter, ou ainda remove caracteres da cadeia1.

As principais opções do comando são:

Principais Opções do comando tr
-d   Remove os caracteres de cadeia1  
  Opção     Significado  
-s   Comprime n ocorrências de cadeia1 em apenas uma  

Trocando caracteres com tr

Primeiro vou te dar um exemplo bem bobo:

$ echo bobo | tr o a baba

Isto é, troquei todas as ocorrências da letra o pela letra a.

Suponha que em um determinado ponto do meu script eu peça ao operador para teclar s ou n (sim ou não), e guardo sua resposta na variável $Resp. Ora o conteúdo de $Resp pode estar com letra maiúscula ou minúscula, e desta forma eu teria que fazer diversos testes para saber se a resposta dada foi S, s, N ou n. Então o melhor é fazer:

$ Resp=$(echo $Resp | tr SN sn)

e após este comando eu teria certeza que o conteúdo de $Resp seria um s ou um n.

Se o meu arquivo ArqEnt está todo escrito com letras maiúsculas e desejo passá-las para minúsculas eu faço:

$ tr A-Z a-z < ArqEnt > /tmp/$$ $ mv -f /tmp/$$ ArqEnt

Note que neste caso usei a notação A-Z para não escrever ABCD...YZ. Outro tipo de notação que pode ser usada são as escape sequences (prefiro escrever no bom e velho português, mas nesse caso como eu traduziria? Seqüências de escape? Meio sem sentido, né? Mas vá lá...) que também são reconhecidas por outros comandos e também na linguagem C, e cujo significado você verá a seguir:

Escape Sequences
\\   Uma barra invertida   \0134
  Seqüência     Significado     Octal  
\t   Tabulação   \011
\n   Nova linha   \012
\v   Tabulação Vertical   \013
\f   Nova Página   \014
\r   Início da linha <^M>   \015

Removendo caracteres com tr

Então deixa eu te contar um "causo": um aluno que estava danado comigo, resolveu complicar a minha vida e em um exercício prático valendo nota que passei para ser feito no computador, me entregou o script com todos os comandos separados por ponto-e-vírgula (lembra que eu disse que o ponto-e-vírgula servia para separar diversos comandos em uma mesma linha?).

Vou dar um exemplo simplificado e idiota de uma "tripa" assim:

$ cat confuso echo leia Programação Shell Linux do Julio Cezar Neves > livro;cat livro;pwd;ls;rm -f lixo 2>/dev/null;cd ~

Eu executava o programa e ele funcionava:

$ confuso leia Programação Shell Linux do Julio Cezar Neves /home/jneves/LM confuso livro musexc musicas musinc muslist numeros

Mas nota de prova é coisa séria (e nota de dólar é mais ainda :)) então, para entender o que o aluno havia feito, o chamei e em sua frente executei o seguinte comando:

$ tr ";" "\n" < confuso echo leia Programação Shell Linux do Julio Cezar Neves pwd ls rm -f lixo 2>/dev/null cd ~

O cara ficou muito desapontado, porque em 2 ou 3 segundos eu desfiz a gozação que ele perdera horas para fazer.

Mas preste atenção! Se eu estivesse em uma máquina com Unix, eu teria feito:

$ tr ";" "\012" < confuso

Xpremendo com tr

Agora veja a diferença entre os dois comandos date: o que fiz hoje e outro que foi executado há duas semanas:

$ date # Hoje Sun Sep 19 14:59:54 2004 $ date # Há duas semanas Sun Sep 5 10:12:33 2004

Para pegar a hora eu deveria fazer:

$ date | cut -f 4 -d ' ' 14:59:54

Mas duas semanas antes ocorreria o seguinte:

$ date | cut -f 4 -d ' ' 5

Mas observe porque:

$ date # Há duas semanas Sun Sep 5 10:12:33 2004

Como você pode notar, existem 2 caracteres em branco antes do 5 (dia), o que estraga tudo porque o terceiro pedaço está vazio e o quarto é o dia (5). Então o ideal seria comprimir os espaços em brancos sucessivos em somente um espaço para poder tratar as duas cadeias resultantes do comando date da mesma forma, e isso se faz assim:

$ date | tr -s " " Sun Sep 5 10:12:33 2004

Como você pode ver não existem mais os dois espaços, então agora eu poderia cortar:

$ date | tr -s " " | cut -f 4 -d " " 10:12:33

Olha só como o Shell já está quebrando o galho. Veja este arquivo que foi baixado de uma máquina com aquele sistema operacional que pega vírus:

$ cat -ve ArqDoDOS.txt Este arquivo^M$ foi gerado pelo^M$ DOS/Rwin e foi^M$ baixado por um^M$ ftp mal feito.^M$

E agora eu quero te dar duas dicas:

Pinguim com placa de dica Dica #1 - A opção -v do cat mostra os caracteres de controle invisíveis, com a notação ^L, onde ^ é a tecla control e L é a respectiva letra. A opção -e mostra o final da linha como um cifrão ($).

Pinguim com placa de dica Dica #2 - Isto ocorre porque no formato DOS (ou rwin), o fim dos registros é formado por um carriage-return (\r) e um line-feed (\n). No Linux porém o final do registro tem somente o line-feed.

Vamos então limpar este arquivo.

$ tr -d '\r' < ArqDoDOS.txt > /tmp/$$ $ mv -f /tmp/$$ ArqDoDOS.txt

Agora vamos ver o que aconteceu:

$ cat -ve ArqDoDOS.txt Este arquivo$ foi gerado pelo$ DOS/Rwin e foi$ baixado por um$ ftp mal feito.$

Bem a opção -d do tr remove o caractere especificado de todo o arquivo. Desta forma eu removi os caracteres indesejados salvando em um arquivo de trabalho e posteriormente renomeei-o para a sua designação original.

Obs: No Unix eu deveria fazer:

$ tr -d '\015' < ArqDoDOS.txt > /tmp/$$

Pinguim com placa de atenção Isto aconteceu porque o ftp foi feito do modo binário (ou image), isto é, sem a interpretação do texto. Se antes da transmissão do arquivo tivesse sido estipulada a opção ascii do ftp, isto não teria ocorrido.

     - Olha, depois desta dica tô começando a gostar deste tal de Shell, mas ainda tem muita coisa que não consigo fazer.

     - Pois é, ainda não te falei quase nada sobre programação em Shell, ainda tem muita coisa para aprender, mas com o que aprendeu, já dá para resolver muitos problemas, desde que você adquira o “modo Shell de pensar”. Você seria capaz de fazer um script para me dizer quais são as pessoas que estão “logadas” há mais de um dia no seu servidor?

     - Claro que não! Para isso seria necessário eu conhecer os comandos condicionais que você ainda não me explicou como funcionam.

    - Deixa eu tentar mudar um pouco a sua lógica e trazê-la para o “modo Shell de pensar”, mas antes é melhor tomarmos um chope... Ô Chico, traz mais dois...

     - Agora que já molhei a palavra, vamos resolver o problema que te propus. Repare como funciona o comando who:

$ who jneves pts/1 Sep 18 13:40 rtorres pts/0 Sep 20 07:01 rlegaria pts/1 Sep 20 08:19 lcarlos pts/3 Sep 20 10:01

E veja também o date:

$ date Mon Sep 20 10:47:19 BRT 2004

Repare que o mês e o dia estão no mesmo formato em ambos os comandos.

Pinguim com placa de dica Algumas vezes um comando tem a saída em português e o outro em inglês. Quando isso ocorrer, você pode usar o seguinte artifício:
$ date Mon Sep 20 10:47:19 BRT 2004 $ LANG=pt_BR date Seg Set 20 10:47:19 BRT 2004
Desta forma passando a saída do comando date para português.

Ora, se em algum registro do who eu não encontrar a data de hoje, é sinal que o cara está "logado" há mais de um dia, já que ele não pode ter se "logado" amanhã... Então vamos guardar o pedaço que importa da data de hoje para procurá-la na saída do who:

$ Data=$(date | cut -c 5-10)

Eu usei a construção $(...), para priorizar a execução dos comandos antes de atribuir a sua saída à variável $Data. Vamos ver se funcionou:

$ echo $Data Sep 20

Beleza! Agora, o que temos que fazer é procurar no comando who os registros que não possuem esta data.

     - Ah! Eu acho que estou entendendo! Você falou em procurar e me ocorreu o comando grep, estou certo?

     - Certíssimo! Só que eu tenho que usar o grep com aquela opção que ele só lista os registros nos quais ele não encontrou a cadeia. Você se lembra que opção é essa?

     - Claro, é a opção -v...

     - Isso! Tá ficando bão! Então vamos ver:

$ who | grep -v "$Data" jneves pts/1 Sep 18 13:40

     - E se eu quisesse mais um pouco de perfumaria eu faria assim:

$ who | grep -v "$Data" | cut -f1 -d ' ' jneves

     - Viu? Não foi necessário usar nenhum comando condicional, até porque o nosso mais usado comando condicional, o famoso if, não testa condição, mas sim instruções, como veremos agora.

Comandos Condicionais

Veja as linhas de comando a seguir:

$ ls musicas musicas $ echo $? 0 $ ls ArqInexistente ls: ArqInexistente: No such file or directory $ echo $? 1 $ who | grep jneves jneves pts/1 Sep 18 13:40 (10.2.4.144) $ echo $? 0 $ who | grep juliana $ echo $? 1

     - O que é esse $? faz aí? Começando por cifrão ($) parece ser uma variável, certo?

     - Sim é uma variável que contém o código de retorno da última instrução executada. Posso te garantir que se esta instrução foi bem sucedida, $? terá o valor zero, caso contrário seu valor será diferente de zero.

O Comando if

O que o nosso comando condicional if faz é testar a variável $?. Então vamos ver a sua sintaxe:

    if cmd
    then
        cmd1
        cmd2
        cmdn
    else
        cmd3
        cmd4
        cmdm
    fi

ou seja: caso comando cmd tenha sido executado com sucesso, os comandos do bloco do then (cmd1, cmd2 e cmdn) serão executados, caso contrário, os comandos executados serão os do bloco opcional do else (cmd3, cmd4 e cmdm), terminando com um fi.

Vamos ver na prática como isso funciona usando um scriptizinho que serve para incluir usuários no /etc/passwd:

$ cat incusu #!/bin/bash # Versão 1 if grep ^$1 /etc/passwd then echo Usuario \'$1\' já existe else if useradd $1 then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi

Repare que o if está testando direto o comando grep e esta é a sua finalidade. Caso o if seja bem sucedido, ou seja, o usuário (cujo nome está em $1) foi encontrado em /etc/passwd, os comandos do bloco do then serão executados (neste exemplo é somente o echo) e caso contrário, as instruções do bloco do else é que serão executadas, quando um novo if testa se o comando useradd foi executado a contento, criando o registro do usuário em /etc/passwd, ou não quando dará a mensagem de erro.
Vejamos sua execução, primeiramente passando um usuário já cadastrado:

$ incusu jneves jneves:x:54002:1001:Julio Neves:/home/jneves:/bin/bash Usuario 'jneves' ja existe

Como já vimos diversas vezes, mas é sempre bom insistir no tema para que você já fique precavido, no exemplo dado surgiu uma linha indesejada, ela é a saída do comando grep. Para evitar que isso aconteça, devemos desviar a saída desta instrução para /dev/null, ficando assim:

$ cat incusu #!/bin/bash # Versão 2 if grep ^$1 /etc/passwd > /dev/null # ou: if grep -q ^$1 /etc/passwd then echo Usuario \'$1\' já existe else if useradd $1 then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi

Agora vamos testá-lo como usuário normal (não root):

$ incusu ZeNinguem ./incusu[6]: useradd: not found Problemas no cadastramento. Você é root?

Epa, aquele erro não era para acontecer! Para evitar que isso aconteça devemos mandar também a saída de erro (strerr, lembra?) do useradd para /dev/null, ficando na versão final assim:

$ cat incusu #!/bin/bash # Versão 3 if grep ^$1 /etc/passwd > /dev/null then echo Usuario \'$1\' já existe else if useradd $1 2> /dev/null then echo Usuário \'$1\' incluído em /etc/passwd else echo "Problemas no cadastramento. Você é root?" fi fi

Depois destas alterações e de fazer um su – (me tornar root) vejamos o seu comportamento:

$ incusu botelho Usuário 'botelho' incluido em /etc/passwd

E novamente:

$ incusu botelho Usuário 'botelho' já existe

Lembra que eu falei que ao longo dos nossos papos e chopes os nossos programas iriam se aprimorando? Então vejamos agora como poderíamos melhorar o nosso programa para incluir músicas:

$ cat musinc #!/bin/bash # Cadastra CDs (versao 3) # if grep "^$1$" musicas > /dev/null then echo Este álbum já está cadastrado else echo $1 >> musicas sort musicas -o musicas fi

Como você viu, é uma pequena evolução da versão anterior, assim, antes de incluir um registro (que pela versão anterior poderia ser duplicado), testamos se o registro começava (^) e terminava ($) igual ao parâmetro passado ($1). O uso do circunflexo (^) no início da cadeia e cifrão ($) no fim, são para testar se o parâmetro passado (o álbum e seus dados) são exatamente iguais a algum registro anteriormente cadastrado e não somente igual a um pedaço de algum dos registros.

Vamos executá-lo passando um álbum já cadastrado:

$ musinc "album 4^Artista7~Musica7:Artista8~Musica8" Este álbum já está cadastrado

E agora um não cadastrado:

$ musinc "album 5^Artista9~Musica9:Artista10~Musica10" $ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8 album 5^Artista9~Musica9:Artista10~Musica10

     - Como você viu, o programa melhorou um pouquinho, mas ainda não está pronto. À medida que eu for te ensinando a programar em shell, nossa CDteca irá ficando cada vez melhor.

     - Entendi tudo que você me explicou, mas ainda não sei como fazer um if para testar condições, ou seja o uso normal do comando.

     - Cara, para isso existe o comando test, ele é que testa condições. O comando if testa o comando test. Mas isso está meio confuso e como já falei muito, estou precisando de uns chopes para molhar a palavra. Vamos parando por aqui e na próxima vez te explico direitinho o uso do test e de diversas outras sintaxes do if.

     - Falou! Acho bom mesmo porque eu também já tô ficando zonzo e assim tenho tempo para praticar esse monte de coisas que você me falou hoje.

     - Para fixar o que você aprendeu, tente fazer um scriptizinho para informar se um determinado usuário, que será passado como parâmetro esta logado (arghh!) ou não.

     - Aê Chico, mais dois chopes por favor...

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