Como redirecionar a entrada padrão da instrução 'while' em um arquivo?

0

Estou aprendendo sobre shell scripts e tenho algumas dificuldades em entender o desenvolvimento das principais estruturas de comando necessárias para escrever um script, especialmente com os comandos while , do e done .

Eu sei que ao redirecionar a entrada padrão da instrução while de um arquivo, ele irá parar assim que todo o arquivo for lido (nesse caso, o arquivo é lido linha por linha e a linha atual é colocada em uma variável usada por read ):

while read lig fich
do
...
done < fich

significa que temos uma linha inteira inteira em fich ?

Por exemplo: esse script usa um nome de usuário e uma string como argumentos, ele procura por arquivos fornecidos pelo nome de usuário e cujo nome contém a string:

#usage nblign nom-utilisateur chaine
find . -user $1 | grep $2 >temp
while read lig temp
do
echo $lig "nombre de ligne" 'wc -l < $lig'$
done < temp
rm temp

Aqui, meu professor omitiu $ antes de lig in while , é um erro de digitação? Como para obter o resultado de um comando ou uma variável, é necessário usar $ para recuperá-lo.

    
por ThePassenger 10.11.2015 / 00:12

2 respostas

1

Você tem alguns equívocos. Primeiro de tudo, o formato do while read ... do que você está tentando usar é:

while read var; do ...; done < file

E não

while read var file; do ...; done < file

Basicamente, while read var; do ...; done < file lerá cada linha de file e a salvará como var . Qualquer coisa entre read e do é considerada uma variável. Se você der mais de uma variável, a linha será dividida em espaço em branco (bem, no valor da variável $IFS que é \t , \n e espaço, por padrão) e salva nas variáveis fornecidas. Conforme explicado em help read :

Reads a single line from the standard input, or from file descriptor FD if the -u option is supplied. The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on, with any leftover words assigned to the last NAME.

Então, por exemplo:

$ echo "foo bar baz zab" | while read v1 rest; do echo "v1:$v1, rest:$rest"; done
v1:foo, rest:bar baz zab
$ echo "foo bar baz zab" | while read v1 v2 rest; do echo "v1:$v1, v2:$v2, rest:$rest"; done
v1:foo, v2:bar, rest:baz zab
$ echo "foo bar baz zab" | while read v1 v2 v3 rest; do echo "v1:$v1, v2:$v2, v3:$v3, rest:$rest"; done
v1:foo, v2:bar, v3:baz, rest:zab

Como você pode ver acima, a linha de entrada é dividida em quantas variáveis você fornecer. Quando há menos nomes de variáveis do que "palavras" na entrada, a última variável obtém o resto da linha. Isso é exatamente o mesmo ao ler um arquivo.

Em seguida, as variáveis são definidas usando var="foo" e são lidas usando $var . Então, não, seu professor estava certo, você não quer o $ quando a variável está sendo definida. Portanto, while read var está correto e while read $var está errado.

Então, uma versão funcional do seu script, usando a mesma lógica, seria:

find . -user $1 | grep $2 >temp
while read lig 
do
    echo $lig "nombre de ligne" 'wc -l < $lig'
done < temp
rm temp

Observe que removi o temp do read e o $ do final da linha echo . Eu não tenho idéia porque você colocou isso lá.

Uma versão melhorada do seu script, com suas variáveis corretamente citadas , usando find para encontrar as palavras-chave relevantes arquivos em vez de tentar analisar e sem arquivos temporários desnecessários seria:

find . -user "$1" -name "*$2*" |
## No need for a temp file, just pipe the output directly
## to the while loop
while read lig 
do
    echo "$lig nombre de ligne: $(wc -l < "$lig")"
done 

Finalmente, uma abordagem verdadeiramente robusta que, ao contrário do que foi dito acima, pode lidar com nomes de arquivos arbitrários, incluindo aqueles com espaço em branco ou outros caracteres estranhos:

find . -user "$1" -name "*$2*" -print0 |
## No need for a temp file, just pipe the output directly
## to the while loop
while IFS= read -r -d '' lig 
do
    echo "$lig nombre de ligne: $(wc -l < "$lig")"
done 
    
por 10.11.2015 / 12:31
1

De help read : "Leia uma linha da entrada padrão e divida-a em campos." Em outras palavras, ele lê uma linha inteira e tenta dividi-la em três partes diferentes e armazena cada uma dessas partes nas três variáveis que você nomeou. Observe que, se houver apenas uma parte na linha, as outras duas variáveis não serão definidas. Você não usa o $ lá porque você não quer passar o valor atual da variável, mas então nome da variável para que ela saiba que deve set seu valor.

    
por 10.11.2015 / 00:46