Shell Script coisa simples de resolver [RESOLVIDO]

1. Shell Script coisa simples de resolver [RESOLVIDO]

Taffarel
xikara

(usa Outra)

Enviado em 08/11/2014 - 11:20h

Gostaria de saber quantas linha tem a variável LINHA (while read LINHA)



#!/bin/bash
cont=0
aux=1
asterisk -rx "khomp channels show" | egrep "GSM|R2br|FXO|FXS" | while read LINHA; do

for((i=0;$i < ${#LINHA}; i++)){
if [ "${LINHA:$i:4}" == 'R2br' ]; then
#echo "${LINHA:$i:4}"
cont=$((cont + 1))
R2br=$((cont + 1))
fi

if [ "${LINHA:$i:3}" == 'GSM' ]; then
#echo "${LINHA:$i:4}"
cont=$((cont + 1))
GSM=$((cont + 1))
fi
if [ "${LINHA:$i:3}" == 'FXO' ]; then
#echo "${LINHA:$i:4}"
cont=$((cont + 1))
FXO=$((cont + 1))
fi
if [ "${LINHA:$i:3}" == 'FXS' ]; then
#echo "${LINHA:$i:4}"
cont=$((cont + 1))
FXS=$((cont + 1))
fi

}

echo "$R2br Tipos: R2br"
echo "$R2br Tipos: GSM"
echo "$FXO Tipos: FXO"
echo "$FXS Tipos: FXS"

done;


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/11/2014 - 05:40h

Como disse o colega, acima, seria melhor você explicar direito o que quer.

Sua dúvida parece relacionada a de outro tópico que você criou. Fico feliz que você tenha deixado de lado a ideia de colocar várias linhas numa variável só. No entanto, eu particularmente não gosto da sintaxe

«comando que produz várias linhas» | while read «variáveis»; do
# Extrai valores a partir de variáveis
«comandos»
done


porque a pipeline provoca a criação de um outro processo. No caso acima, todo o bloco que vai do sinal | até o done fica nesse processo separado, e isso significa que qualquer variável que tenha sido definida ou alterada dentro do laço de repetição não terá tais definições ou alterações visíveis quando o laço acabar. Além disso, se algum comando dentro do laço de repetição tentar ler alguma coisa, essa leitura vai interferir com a fonte de dados do próprio while read. Por essas razões, eu prefiro a seguinte sintaxe, usando descritores auxiliares.

# O descritor de arquivos número 3 é associado à saída do comando.
exec 3< <(«comando que produz várias linhas»)

# Redireciona somente a leitura das variáveis
while read «variáveis» <&3; do
# Aqui dentro, outros comandos que façam leitura mas que não
# estejam explicitamente com o redirecionamento “<&3” não vão
# interferir com a leitura das variáveis.
«comandos»
done

# Libera (fecha) o descritor auxiliar
exec 3<&-


No seu código, aquele for me parece uma tentativa de procurar ocorrências múltiplas de um conjunto de strings dentro da mesma linha. Parece-me que isso deveria funcionar, mas tenho receio de que você esteja fazendo de uma forma pouco eficiente.

Um jeito rápido de fazer sem while nem for, mas usando comandos externos, seria com a opção “-o” do GNU grep. Por exemplo:

«comando que gera múltiplas linhas» > arquivo_temporário
cont_FXS=`grep -o FXS arquivo_temporário | wc -l`
cont_FXO=`grep -o FXO arquivo_temporário | wc -l`
# etc...
rm -f arquivo_temporário


Outro modo, sem chamar comando externo, seria com outro tipo substituição do Bash, que remove prefixos.

while read linha <&3; do
a="$linha"
while : ; do
b="${a#*FXS}"
[[ "$b" = "$a" ]] && break
a="$b"
((cont_FXS++))
done

a="$linha"
while : ; do
b="${a#*FXO}"
[[ "$b" = "$a" ]] && break
a="$b"
((cont_FXO++))
done

# etc...
done


Para você saber, o Bash é ruim de desempenho com manipulação de strings e péssimo com aritmética. Mesmo normalmente preferindo evitar comandos externos, eu recomendo a sugestão com “grep -o” e “wc -l”. Sò para lhe dar uma ideia, eis uma comparação de desempenho entre comandos análogos ao que você fez e às duas sugestões que eu dei, contando ocorrência do string "man" na lista de arquivos da minha máquina (que tem um total de 345208 arquivos, ou linhas de entrada).

$ # Análogo ao que você fez: tempo de referência.
$ time locate "" | bash -c 'cont=0; while read linha; do for ((i=0; i<${#linha}-2; i++)); do if [[ ${linha:$i:3} = man ]]; then ((cont++)); fi; done; done; echo $cont'
36494

real 4m12.240s
user 3m58.714s
sys 0m13.982s


$ # Com grep -o e wc -l: 1510 vezes mais rápido!!!
$ time locate "" | grep -o man | wc -l
36494

real 0m0.167s
user 0m0.224s
sys 0m0.062s


$ # Extração de prefixos: 7,69 vezes mais rápido.
$ time locate "" | bash -c 'cont=0; while read linha; do a="$linha"; while :; do b=${a#*man}; [[ "$b" = "$a" ]] && break; a="$b"; ((cont++)); done; done; echo $cont'
36494

real 0m32.803s
user 0m17.763s
sys 0m15.319s


Com Perl, fica um pouco mais interessante:

$ time locate "" | perl -ne '
BEGIN {
@palavras=qw(share man obj kernel src module etc usr root);
$padrao=join("|", @palavras);
foreach $str (@palavras){
$cont{$str}=0;
}
}

while(s/.*?($padrao)//){
$cont{$1}++;
}

END {
foreach $str (@palavras){
print "Ocorrências de \"$str\": $cont{$str}\n";
}
}
'
Ocorrências de "share": 158878
Ocorrências de "man": 36494
Ocorrências de "obj": 874
Ocorrências de "kernel": 10999
Ocorrências de "src": 125461
Ocorrências de "module": 12269
Ocorrências de "etc": 3673
Ocorrências de "usr": 315613
Ocorrências de "root": 318

real 0m1.681s
user 0m1.833s
sys 0m0.156s


3. Re: Shell Script coisa simples de resolver [RESOLVIDO]

luiz
luizsouza99

(usa Linux Mint)

Enviado em 10/11/2014 - 03:09h

explica melhor o q vc quer, sua pergunta esta meio vaga.

se não me engano váriavel não tem linha, podemos contar linhas de um arquivo, ou vc quer saber o valor da várivel com relação ao loop?

fala o que vc precisa, talvez tenhamos algum jeito de fazer a mesma coisa com outros codigos.


4. obrigado a todos

Taffarel
xikara

(usa Outra)

Enviado em 10/11/2014 - 09:40h

No código shell script acima. Como qualquer variável dentro de um while depois que sai do while ela perde o valor.Gostaria de um comando falace quantas linhas tem o variável.Pois na hora que for o ultimo registro eu imprimir
Tipo assim

linha 1
linha 2
linha 3

total 3 linha


5. Re: Shell Script coisa simples de resolver [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/11/2014 - 09:55h

Não é qualquer while que não preserva valor. Leia de novo o que eu disse. Só não se preserva vlaor quando você faz num processo separado (por exemplo, por causa de pipeline). Se você mantiver tudo no mesmo processo -- e eu mostrei um jeito de fazer e o expliquei --, não perde valor coisa nenhuma.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts