Faz o loop através do arquivo de guia delineado no script bash

17

Aqui está o que eu tenho até agora:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

E uma amostra do arquivo de entrada:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

E saída do script:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

Por algum motivo, cada variável é definida para a linha inteira. Quando eu uso echo users.txt | cut -f1 na linha de comando, ele retorna o token muito bem.

    
por mortona42 21.06.2012 / 01:13

2 respostas

6

Que tal isso?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

Eu não sei dizer se você tem um problema para resolver, ou está se perguntando sobre uma questão mais teórica.

    
por 21.06.2012 / 01:17
20

O problema está no comando echo $line . Como não há cotações em torno de $line , o shell executa a divisão de palavras nele e interpreta cada palavra como um padrão de globbing. Experimente com

a='*.txt foo'
ls $a

No seu caso, as guias separam as palavras, que se tornam argumentos separados para echo . O comando echo imprime seus argumentos separados por um espaço. Portanto, cut acaba recebendo campos delimitados por espaço em vez de campos delimitados por tabulações.

Sempre coloque aspas duplas em torno das substituições de variáveis $foo e substituições de comandos $(foo) (a menos que você entenda por que precisa deixá-las de fora e por que não há problema em fazê-lo). echo "$line" funcionaria aqui, mas é uma maneira complicada de fazer o que você propõe.

Mantendo sua abordagem de análise no shell, você pode fazer com que o comando read analise a entrada nos campos.

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

read divide os campos separados por caracteres no valor da variável IFS , que consiste em um espaço e uma tabulação (além de uma nova linha, que não pode ocorrer dentro de uma linha) por padrão. Para dividir apenas nas guias, defina IFS para uma única guia primeiro. Observe que as guias inicial e final são ignoradas e as guias consecutivas contam como uma única.

read trata \ como um caractere especial: uma barra invertida seguida por uma nova linha é ignorada; \ se torna uma única barra invertida. Se você quiser evitar esse comportamento, passe a opção -r .

    
por 21.06.2012 / 02:04

Tags