Estou usando sh (não bash/csh) no FreeBSD 11 e não entendo isso:
Na consola
Comando:zpool status -v
Resultado:
pool: My_pool
state: ONLINE
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
Dividindo por linhas e imprimindo linha por vez em um script:
#!/bin/sh
zp="$(zpool status -v)"
for line in $zp; do
echo "$line%"
done
Resultado:
pool:%
My_pool%
state:%
ONLINE%
status:%
One%
or%
more%
devices%
is%
currently%
being%
resilvered.%
The%
pool%
will%
continue%
to%
function,%
possibly%
in%
a%
degraded%
state.%
action:%
Wait%
De acordo com tudo o que encontrei, a sintaxe que estou usando é correta para sh e deve ler uma linha por vez, não uma palavra por vez.
o que estou perdendo?
Responder1
Estou intrigado com o que você encontrou. A sintaxe que você usou está correta para sh e divisões em espaços em branco, não apenas em novas linhas. Isto está amplamente documentado. Pensar que ele se divide nas quebras de linha não é um equívoco popular. (Não entender que isso se divide é um equívoco popular.)
Mais precisamente, deixar uma expansão variável sem aspas, como em $zp
, às vezes é apelidado de operador “split+glob”. O que isso faz é:
- Pegue o valor da variável. Isso é uma corda.
- Divida esse valor em cada caractere separador de campo. Um caractere separador de campo é aquele que está no valor da variável
IFS
; por padrão, esta variável contém umespaço, uma tabulação e uma nova linha. (Esse padrão também é usado se a variável não estiver definida.) O resultado é uma lista de strings. - Considere cada elemento da lista como um padrão curinga (glob). Se corresponder a um ou mais nomes de arquivos, esse elemento será substituído pela lista de nomes de arquivos correspondentes. Caso contrário, o elemento será deixado sozinho.
Por exemplo, se o diretório contiver arquivos chamados foo
, bar
e baz
, o script a seguir imprimirá três linhas: a*
, bar
e baz
.
zq='a* b*'
for word in $zq; do echo "$word"; done
Se quiser dividir uma string em novas linhas, você pode fazer isso configurando IFS
uma nova linha e desativando a expansão de curinga.
#!/bin/sh
set -f
IFS='
'
zq=…
for line in $zq; do
…
done
Isso se aplica a todas as variantes sh e csh.
Veja tambémPor que meu script de shell engasga com espaços em branco ou outros caracteres especiais?
Responder2
Para ler linhas, use o recurso interno do seu shelllerfunção,
$ajuda a ler | cabeça -2
leitura: leitura [-ers] [-u fd] [-t tempo limite] [-p prompt] [-a array] [-n nchars] [-d delim] [nome ...]
Uma linha é lida da entrada padrão ou do descritor de arquivo FD se a opção -u for fornecida
Coloque-o dentro de um while
loop e pronto, você terá linhas:
$ wc -l -w ~/.profile
24 47 /Users/jklowden/.profile
$ for W in $(cat ~/.profile); do echo $W; done | wc -l
47
$ while read L; do echo $L; done < ~/.profile | wc -l
24