Discussion:
[shell-script] SED - como ir selecionando trechos de acordo com um padrão
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-16 17:12:11 UTC
Permalink
Boa tarde pessoal.

Eu estava fazendo um script onde irá executar um outro script de acordo com
as informações de um certo arquivo:

.CADIRTEWS

Capture Connector: object=user_password,dv=so_sicredi_ad

Apply Connector:
object=tews_sicrediUsuario_merge,dv=so_caidmtews_userpassword

Transformation: ADUserPassword_To_CAIDMTewsPassword

Capture Connector: object=entidades_merge,dv=so_sicredi_oid_entities

Apply Connector:
object=tews_SicrediOrganization,dv=so_caidmtews_entidades_org

Transformation: OIDEntitiesOU_To_CADIRTEWSEntidadesOU

.CADIRIDS

Components for topology: CADIRIDS

Capture Connector: object=SicrediNumberID,dv=so_sicredi_cadir_ids

Apply Connector: object=SicrediNumberID,dv=so_sicredi_oldap_ids

Transformation: CADIRIds_To_OLDAPIds

Apply Connector: object=SicrediNumberID,dv=so_sicredi_oid_ids

Transformation: CADIRIds_To_OIDIds

.CADIRENTIDADESOU

Capture Connector:
object=SicrediOrganization_merge,dv=so_sicredi_cadir_entidades

Apply Connector: object=entidades_merge,dv=so_sicredi_oid_entities

Transformation: CADIREntidadesOU_To_OIDEntitiesOU

Capture Connector:
object=SicrediOrganization_merge_deletion,dv=so_sicredi_cadir_entidades

Apply Connector: object=entidades_merge,dv=so_sicredi_oldap_entities

Transformation: CADIREntidadesOU_To_OLDAPEntitiesOUDelete

Transformation: CADIREntidadesOU_To_OIDEntitiesOUDelete

Transformation: CADIREntidadesOU_To_OLDAPEntitiesOU

Como podem ver, o início de cada trecho há um '.' e o final há uma linha
vazia. Minha intenção é selecionar cada trecho, processá-lo e passar para o
próximo trecho. Não há necessidade de criar um loop, somente eu tiver uma
forma de usar o sed e manipular os trechos de acordo com a sua ordem. Sei
que eu posso tratar com outros métodos, mas eu fiquei curioso como o SED
poderia manipular.

O que eu já tentei:

[***@app1ssosite006h bin]# sed -n '1,/^\./p' listas_conectores.txt

/opt/radiantone/vds/r1syncsvcs/bin

.CADIRTEWS

[***@app1ssosite006h bin]# sed -n '2,/^\./p' listas_conectores.txt

.CADIRTEWS

Capture Connector: object=user_password,dv=so_sicredi_ad

Apply Connector:
object=tews_sicrediUsuario_merge,dv=so_caidmtews_userpassword

Transformation: ADUserPassword_To_CAIDMTewsPassword

Capture Connector: object=entidades_merge,dv=so_sicredi_oid_entities

Apply Connector:
object=tews_SicrediOrganization,dv=so_caidmtews_entidades_org

Transformation: OIDEntitiesOU_To_CADIRTEWSEntidadesOU

.CADIRIDS

[***@app1ssosite006h bin]#


[***@app1ssosite006h bin]# sed -n '/^\./{p;1q}' listas_conectores.txt

.CADIRTEWS

.CADIRIDS

.CADIRENTIDADESOU

.CADIRSEGURANCA

.CADIRDISTRIBUICAO

.CADIRUSERS

.CADIRENTIDADESGROUP

.CADIRTOVDSTOCADIR

.COMPUTE

Obrigado!
itamarnet@yahoo.com.br [shell-script]
2016-09-17 12:33:40 UTC
Permalink
Caro Édnei

Fiquei com algumas dúvidas sobre o que deseja e sobre o arquivo de exemplo:
1 - A cada trecho que começa por uma linha iniciado por um ponto ( como vc descreveu ), seguida de letras maúsculas até o final da linha ( minha dedução cujo regex seria "/\.[A-Z]+$/" ) e que também poderia ser linhas iniciadas por ".CADIR", e outra por ".COMPUTE".

2 - O final de cada bloco há uma linha vazia, todavia no exemplo que passou não chegou contendo. Isso pode ser um problema pela maneira como chegou via o fórum, por isso pergunto.
Se for isso a segunda parte da regex poderia ser limitada assim /^$/ ou /^[[:blank:]]*$/ se houver a possibilidade de conter espaços ou tabulações.

3 - O último comando que lista apenas os "títulos" não deveria ser:
$ sed -n '/^\./p' listas_conectores.txt
Do jeito que passou comigo listou apenas um, e não todos.

4 - Para cada trecho desejado vc quer fazer um processamento distinto dentro do sed.
Se é isso um filtro generalista de começo não serve, como a regex "/\.[A-Z]+$/" que sugeri a pouco e talvez o uso por limite inicial por número da linha como vc usou pode ser ineficaz, caso o conteúdo seja variável.
Para isso vc pode montar os blocos definindo explicitamente o começo e o final, por exemplo:
$ sed -n '/\.CADIRIDS/,/^$/ {
*** comandos para esse trecho ***
p
}' listas_conectores.txt

ou se precisar limitar o fim de outra forma com o uso do ponto inicial:
$ sed -n '/\.CADIRIDS/,/^\./ {
/\./ { /\.CADIRIDS/!q; }
*** comandos para esse trecho ***
p
}' listas_conectores.txt


Não sei se fui claro em minhas dúvidas e se o que sugeri lhe ajuda.

De toda forma, seria como abordaria usando o sed.

[]'s
Itamar
'Julio C. Neves' julio.neves@gmail.com [shell-script]
2016-09-17 12:45:04 UTC
Permalink
Itamar, não havia respondido nada, pq minhas dúvidas foram exatamente
iguais às suas.
Post by ***@yahoo.com.br [shell-script]
Caro Édnei
1 - A cada trecho que começa por uma linha iniciado por um ponto ( como vc
descreveu ), seguida de letras maúsculas até o final da linha ( minha
dedução cujo regex seria "/\.[A-Z]+$/" ) e que também poderia ser linhas
iniciadas por ".CADIR", e outra por ".COMPUTE".
2 - O final de cada bloco há uma linha vazia, todavia no exemplo que
passou não chegou contendo. Isso pode ser um problema pela maneira como
chegou via o fórum, por isso pergunto.
Se for isso a segunda parte da regex poderia ser limitada assim /^$/ ou
/^[[:blank:]]*$/ se houver a possibilidade de conter espaços ou tabulações.
$ sed -n '/^\./p' listas_conectores.txt
Do jeito que passou comigo listou apenas um, e não todos.
4 - Para cada trecho desejado vc quer fazer um processamento distinto dentro do sed.
Se é isso um filtro generalista de começo não serve, como a regex
"/\.[A-Z]+$/" que sugeri a pouco e talvez o uso por limite inicial por
número da linha como vc usou pode ser ineficaz, caso o conteúdo seja
variável.
Para isso vc pode montar os blocos definindo explicitamente o começo e o
$ sed -n '/\.CADIRIDS/,/^$/ {
*** comandos para esse trecho ***
p
}' listas_conectores.txt
$ sed -n '/\.CADIRIDS/,/^\./ {
/\./ { /\.CADIRIDS/!q; }
*** comandos para esse trecho ***
p
}' listas_conectores.txt
Não sei se fui claro em minhas dúvidas e se o que sugeri lhe ajuda.
De toda forma, seria como abordaria usando o sed.
[]'s
Itamar
Rodrigo Cunha rodrigo.root.rj@gmail.com [shell-script]
2016-09-17 17:01:39 UTC
Permalink
Ednei,crie uma amostra pra galera entender qual é a sua finalidade,
coloque em anexo um arquivo a ser processado (INPUT) e mais dois; um
contendo um arquivo com o processamento desejado e um contendo um arquivo
com o erro que vc encontrou.
Lógicamente, crie os arquivos com uma pequena amostra, vai ser mais simples
de entender o que vc quer fazer.
Abração!
Post by 'Julio C. Neves' ***@gmail.com [shell-script]
Itamar, não havia respondido nada, pq minhas dúvidas foram exatamente
iguais às suas.
Post by ***@yahoo.com.br [shell-script]
Caro Édnei
1 - A cada trecho que começa por uma linha iniciado por um ponto ( como
vc descreveu ), seguida de letras maúsculas até o final da linha ( minha
dedução cujo regex seria "/\.[A-Z]+$/" ) e que também poderia ser linhas
iniciadas por ".CADIR", e outra por ".COMPUTE".
2 - O final de cada bloco há uma linha vazia, todavia no exemplo que
passou não chegou contendo. Isso pode ser um problema pela maneira como
chegou via o fórum, por isso pergunto.
Se for isso a segunda parte da regex poderia ser limitada assim /^$/ ou
/^[[:blank:]]*$/ se houver a possibilidade de conter espaços ou tabulações.
$ sed -n '/^\./p' listas_conectores.txt
Do jeito que passou comigo listou apenas um, e não todos.
4 - Para cada trecho desejado vc quer fazer um processamento distinto dentro do sed.
Se é isso um filtro generalista de começo não serve, como a regex
"/\.[A-Z]+$/" que sugeri a pouco e talvez o uso por limite inicial por
número da linha como vc usou pode ser ineficaz, caso o conteúdo seja
variável.
Para isso vc pode montar os blocos definindo explicitamente o começo e o
$ sed -n '/\.CADIRIDS/,/^$/ {
*** comandos para esse trecho ***
p
}' listas_conectores.txt
$ sed -n '/\.CADIRIDS/,/^\./ {
/\./ { /\.CADIRIDS/!q; }
*** comandos para esse trecho ***
p
}' listas_conectores.txt
Não sei se fui claro em minhas dúvidas e se o que sugeri lhe ajuda.
De toda forma, seria como abordaria usando o sed.
[]'s
Itamar
--
Atenciosamente,
Rodrigo da Silva Cunha
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-19 16:16:22 UTC
Permalink
Olá pessoal, obrigado pelo interesse.

Eu não respondi antes porque eu trabalhei 15 dias direto e, assim, peguei
esse findi para descansar.

Tentarei explanar melhor qual é a intenção aqui.

Eu tenho um script chamado topology.sh que ao usar como parâmetro
printConnectorStatus, tu podes passar a topologia e o conector. Essa é
sintaxe:

/topology.sh printConnectorStatus CADIRTEWS
object=tews_sicrediUsuario_merge,dv=so_caidmtews_userpassword

Eu já pensei no código e já coloquei num txt todos as topologias e
conectores existentes. Para cada topologia, eu coloquei um '.' no início
para identificá-lo. Para caracterizar o fim da lista de comandos, eu inseri
uma linha em branco.

Minha idéia é ler esse arquivo, montar o comando acima e executar ( o
retorno será um STARTED ou DOWN ) para cada topologia e seus conectores.

Por isso, eu estava tentando montar um SED para pegar a uma Topologia de
vez e ir executando seus respectivos conectores. Logo, pensando numa forma
eficiente, seria algo assim:

Comando SED 'pegar nome depois do .' > TOPOLOGIA_NOME

Comando SED 'PEGAR proxima linha depois do primeiro ponto até a proxima
linha branca' > Arquivo temporário ou Variável

LOOP leitura da saida acima

/.topology.sh printConnectorStatus TOPOLOGIA_NOME Var_loop

Peço desculpas por não ter sido mais rápido na resposta, mas eu estava
cansado mesmo.

Att,

Édnei Rodrigues
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Ednei,crie uma amostra pra galera entender qual é a sua finalidade,
coloque em anexo um arquivo a ser processado (INPUT) e mais dois; um
contendo um arquivo com o processamento desejado e um contendo um arquivo
com o erro que vc encontrou.
Lógicamente, crie os arquivos com uma pequena amostra, vai ser mais
simples de entender o que vc quer fazer.
Abração!
Post by 'Julio C. Neves' ***@gmail.com [shell-script]
Itamar, não havia respondido nada, pq minhas dúvidas foram exatamente
iguais às suas.
Post by ***@yahoo.com.br [shell-script]
Caro Édnei
1 - A cada trecho que começa por uma linha iniciado por um ponto ( como
vc descreveu ), seguida de letras maúsculas até o final da linha ( minha
dedução cujo regex seria "/\.[A-Z]+$/" ) e que também poderia ser linhas
iniciadas por ".CADIR", e outra por ".COMPUTE".
2 - O final de cada bloco há uma linha vazia, todavia no exemplo que
passou não chegou contendo. Isso pode ser um problema pela maneira como
chegou via o fórum, por isso pergunto.
Se for isso a segunda parte da regex poderia ser limitada assim /^$/ ou
/^[[:blank:]]*$/ se houver a possibilidade de conter espaços ou tabulações.
$ sed -n '/^\./p' listas_conectores.txt
Do jeito que passou comigo listou apenas um, e não todos.
4 - Para cada trecho desejado vc quer fazer um processamento distinto dentro do sed.
Se é isso um filtro generalista de começo não serve, como a regex
"/\.[A-Z]+$/" que sugeri a pouco e talvez o uso por limite inicial por
número da linha como vc usou pode ser ineficaz, caso o conteúdo seja
variável.
Para isso vc pode montar os blocos definindo explicitamente o começo e o
$ sed -n '/\.CADIRIDS/,/^$/ {
*** comandos para esse trecho ***
p
}' listas_conectores.txt
$ sed -n '/\.CADIRIDS/,/^\./ {
/\./ { /\.CADIRIDS/!q; }
*** comandos para esse trecho ***
p
}' listas_conectores.txt
Não sei se fui claro em minhas dúvidas e se o que sugeri lhe ajuda.
De toda forma, seria como abordaria usando o sed.
[]'s
Itamar
--
Atenciosamente,
Rodrigo da Silva Cunha
phfbettega@yahoo.com.br [shell-script]
2016-09-19 18:06:37 UTC
Permalink
Olá Édnei, fiz um loop usando bash

while read linha; do
[[ "$linha" =~ ^$ ]] || {
if [[ "$linha" =~ ^\. ]]; then
top_nome="${linha#.}"
continue
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi;}
done <topologias-conectores.txt

A entrada é o que vc postou no primeiro email sem todas as linhas em branco,
só as linhas em branco entre os blocos.
Abraços Paulo
Post by Édnei Rodrigues ***@gmail.com [shell-script]
Olá pessoal, obrigado pelo interesse.
Eu não respondi antes porque eu trabalhei 15 dias direto e, assim, peguei esse findi para descansar.
Tentarei explanar melhor qual é a intenção aqui.
Eu tenho um script chamado topology.sh que ao usar como parâmetro printConnectorStatus, tu podes passar a
/topology.sh printConnectorStatus CADIRTEWS object=tews_sicrediUsuario_merge,dv=so_caidmtews_userpassword
Eu já pensei no código e já coloquei num txt todos as topologias e conectores existentes. Para cada topologia,
eu coloquei um '.' no início para identificá-lo. Para caracterizar o fim da lista de comandos, eu inseri uma
linha em branco.
Minha idéia é ler esse arquivo, montar o comando acima e executar ( o retorno será um STARTED ou DOWN ) para
cada topologia e seus conectores.
Por isso, eu estava tentando montar um SED para pegar a uma Topologia de vez e ir executando seus respectivos
Comando SED 'pegar nome depois do .' > TOPOLOGIA_NOME
Comando SED 'PEGAR proxima linha depois do primeiro ponto até a proxima linha branca' > Arquivo temporário ou
Variável
LOOP leitura da saida acima
/.topology.sh printConnectorStatus TOPOLOGIA_NOME Var_loop
Peço desculpas por não ter sido mais rápido na resposta, mas eu estava cansado mesmo.
Att,
Édnei Rodrigues
__
Ednei,crie uma amostra pra galera entender qual é a sua finalidade, coloque em anexo um arquivo a ser
processado (INPUT) e mais dois; um contendo um arquivo com o processamento desejado e um contendo um
arquivo com o erro que vc encontrou.
Lógicamente, crie os arquivos com uma pequena amostra, vai ser mais simples de entender o que vc quer fazer.
Abração!
__
Itamar, não havia respondido nada, pq minhas dúvidas foram exatamente iguais às suas.
__
Caro Édnei
1 - A cada trecho que começa por uma linha iniciado por um ponto ( como vc descreveu ), seguida de
letras maúsculas até o final da linha ( minha dedução cujo regex seria "/\.[A-Z]+$/" ) e que
também poderia ser linhas iniciadas por ".CADIR", e outra por ".COMPUTE".
2 - O final de cada bloco há uma linha vazia, todavia no exemplo que passou não chegou contendo.
Isso pode ser um problema pela maneira como chegou via o fórum, por isso pergunto.
Se for isso a segunda parte da regex poderia ser limitada assim /^$/ ou /^[[:blank:]]*$/ se houver
a possibilidade de conter espaços ou tabulações.
$ sed -n '/^\./p' listas_conectores.txt
Do jeito que passou comigo listou apenas um, e não todos.
4 - Para cada trecho desejado vc quer fazer um processamento distinto dentro do sed.
Se é isso um filtro generalista de começo não serve, como a regex "/\.[A-Z]+$/" que sugeri a pouco
e talvez o uso por limite inicial por número da linha como vc usou pode ser ineficaz, caso o
conteúdo seja variável.
$ sed -n '/\.CADIRIDS/,/^$/ {
*** comandos para esse trecho ***
p
}' listas_conectores.txt
$ sed -n '/\.CADIRIDS/,/^\./ {
/\./ { /\.CADIRIDS/!q; }
*** comandos para esse trecho ***
p
}' listas_conectores.txt
Não sei se fui claro em minhas dúvidas e se o que sugeri lhe ajuda.
De toda forma, seria como abordaria usando o sed.
[]'s
Itamar
--
Atenciosamente,
Rodrigo da Silva Cunha
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
itamarnet@yahoo.com.br [shell-script]
2016-09-19 18:36:58 UTC
Permalink
A solução do Paulo é perfeita. Simples e objetiva e atende o que deseja pela sua descrição.


Para o que vc deseja o Sed acredito não ter suporte para executar comandos assim, e em puro bash vai direto ao ponto.


A única ressalva que faço é verificar a versão do Shell que está usando, pois o Paulo usou recursos recentes e dependendo da empresa, essa atualização pode ser negligenciada, e os recursos sugeridos podem não funcionar da forma como estão, mas é possível trocar por uso de "test", "sed" ou "grep".


E além de tudo usando esse recursos built-in's, em epecial do Bash há um ganho de performance sem comparação.


[]'s
Itamar
phfbettega@yahoo.com.br [shell-script]
2016-09-19 20:33:42 UTC
Permalink
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não reconhecia função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou 2 pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar comandos assim, e em puro bash vai direto ao
ponto.
A única ressalva que faço é verificar a versão do Shell que está usando, pois o Paulo usou recursos recentes e
dependendo da empresa, essa atualização pode ser negligenciada, e os recursos sugeridos podem não funcionar da
forma como estão, mas é possível trocar por uso de "test", "sed" ou "grep".
E além de tudo usando esse recursos built-in's, em epecial do Bash há um ganho de performance sem comparação.
[]'s
Itamar
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
itamarnet@yahoo.com.br [shell-script]
2016-09-20 11:38:49 UTC
Permalink
Pois é Paulo

Uma coisa que vejo, e parece ser muito comum, é que o Shell, não exclusivamente, tem em sua virtude um dos seus grandes empecilhos.


O fato de ser ágil, confiável, consistente, maduro e duradouro é muitas vezes o motivo para que não seja atualizado.
Por ser algo que funciona bem no que faz, e em muitos casos atendendo casos críticos, atualizações são bloqueadas, e em outros casos não enxergam necessidade de atualizar, visto que o estado atual é perfeitamente funcional.


E na ótica de muitas empresas, vale o dito de que em time que está ganhando não se mexe!


Infelizmente, nem sempre temos a mão os recursos mais avançados do Shell por conta disso. Isso é uma dicotomia, pois não sei se comemoro ou lamento o fato.


[]'s
Itamar
'Julio C. Neves' julio.neves@gmail.com [shell-script]
2016-09-20 11:50:35 UTC
Permalink
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o du
Unix), ele não reconhece função declarada com:
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}

Após declarar uma função, é a prática muito boa fazer:
export -f funcao
Post by ***@yahoo.com.br [shell-script]
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não reconhecia
função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou 2
pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar
comandos assim, e em puro bash vai direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está usando,
pois o Paulo usou recursos recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os
recursos sugeridos podem não funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou
"grep".
Post by ***@yahoo.com.br [shell-script]
E além de tudo usando esse recursos built-in's, em epecial do Bash há um
ganho de performance sem comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-21 12:48:34 UTC
Permalink
Obrigado pela sugestão!

É bem interessante a proposta.
Eu testei a fórmula e houve um erro:

-rwxr-xr-x 1 rluser radiantlogic 249 Sep 21 09:33 status_connector.sh

[***@app1ssosite006h bin]# ./status_connector.sh

./status_connector.sh: line 6: unexpected token `newline', conditional
binary operator expected

./status_connector.sh: line 6: syntax error near `{'

./status_connector.sh: line 6: ` {'

[***@app1ssosite006h bin]# cat status_connector.sh

#!/bin/bash

cat listas_conectores.txt | while read linha;

do

[[ "$linha" =~ ^$]] ||

{

if [[ "$linha" =~ ^\.]]; then

top_nome="${linha#.}"

continue

else

echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"

fi;}

done

[***@app1ssosite006h bin]#

[***@app1ssosite006h bin]# bash --version

bash --version

GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

Copyright (C) 2011 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html
O que significa aquele || ?
Post by 'Julio C. Neves' ***@gmail.com [shell-script]
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}
export -f funcao
Post by ***@yahoo.com.br [shell-script]
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não reconhecia
função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou 2
pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar
comandos assim, e em puro bash vai direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está
usando, pois o Paulo usou recursos recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os
recursos sugeridos podem não funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou
"grep".
Post by ***@yahoo.com.br [shell-script]
E além de tudo usando esse recursos built-in's, em epecial do Bash há
um ganho de performance sem comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
'Julio C. Neves' julio.neves@gmail.com [shell-script]
2016-09-21 13:18:44 UTC
Permalink
Ednei,
[[ ... ]] é um cmd e como tal, deve ter um espaço em branco os separando de
cada um dos operandos que estão no seu interior, pois eles são os
parâmetros que vc está passando para o cmd test.

No código que vc mandou me pareceu não haver espaços antes dos ]], em duas
linhas.

Abcs,
Julio
*@juliobash*

*Próximos cursos de Shell*
*Cidade Local Período*
*​*
*São Paulo 4Linux
<https://www.4linux.com.br/curso/programacao-em-shell-script> 05-09/12*
Dou treinamento de *Shell* em qualquer cidade.
Para mais detalhes, me mande um e-mail <***@gmail.com>.


Em 21 de setembro de 2016 09:48, Édnei Rodrigues
Post by Édnei Rodrigues ***@gmail.com [shell-script]
Obrigado pela sugestão!
É bem interessante a proposta.
-rwxr-xr-x 1 rluser radiantlogic 249 Sep 21 09:33 status_connector.sh
./status_connector.sh: line 6: unexpected token `newline', conditional
binary operator expected
./status_connector.sh: line 6: syntax error near `{'
./status_connector.sh: line 6: ` {'
#!/bin/bash
cat listas_conectores.txt | while read linha;
do
[[ "$linha" =~ ^$]] ||
{
if [[ "$linha" =~ ^\.]]; then
top_nome="${linha#.}"
continue
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi;}
done
bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.
html>
O que significa aquele || ?
Post by 'Julio C. Neves' ***@gmail.com [shell-script]
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}
export -f funcao
Post by ***@yahoo.com.br [shell-script]
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não
reconhecia função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou
2 pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar
comandos assim, e em puro bash vai direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está
usando, pois o Paulo usou recursos recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os
recursos sugeridos podem não funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou
"grep".
Post by ***@yahoo.com.br [shell-script]
E além de tudo usando esse recursos built-in's, em epecial do Bash há
um ganho de performance sem comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
phfbettega@yahoo.com.br [shell-script]
2016-09-21 13:37:46 UTC
Permalink
Olá Mestre Julio, vc tem razão, falta um espaço ali :) às vezes os emails da lista
vem com fonte monoespaçada e às vezes não, pra pegar esses detalhes sem fonte
monoespaçada é uma dificuldade. (sem contar que a indentação também vai pro espaço)
Abraços Paulo
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Ednei,
[[ ... ]] é um cmd e como tal, deve ter um espaço em branco os separando de cada um dos operandos que estão no
seu interior, pois eles são os parâmetros que vc está passando para o cmd test.
No código que vc mandou me pareceu não haver espaços antes dos ]], em duas linhas.
Abcs,
Julio
*
Próximos cursos de Shell*
*Cidade LocalPeríodo*
*
​
**São Paulo 4Linux <https://www.4linux.com.br/curso/programacao-em-shell-script>05
*-09/12*
***
Dou treinamento de /Shell/em qualquer cidade.
__
Obrigado pela sugestão!
É bem interessante a proposta.
-rwxr-xr-x 1 rluser radiantlogic 249 Sep 21 09:33 status_connector.sh
./status_connector.sh: line 6: unexpected token `newline', conditional binary operator expected
./status_connector.sh: line 6: syntax error near `{'
./status_connector.sh: line 6: ` {'
#!/bin/bash
cat listas_conectores.txt | while read linha;
do
[[ "$linha" =~ ^$]] ||
{
if [[ "$linha" =~ ^\.]]; then
top_nome="${linha#.}"
continue
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi;}
done
bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html
<http://gnu.org/licenses/gpl.html>>
O que significa aquele || ?
__
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o du Unix), ele não reconhece
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}
export -f funcao
__
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não reconhecia função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou 2 pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar comandos assim, e em puro bash
vai direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está usando, pois o Paulo usou
recursos recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os recursos sugeridos podem
não funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou "grep".
E além de tudo usando esse recursos built-in's, em epecial do Bash há um ganho de performance
sem comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-21 14:21:16 UTC
Permalink
Senhores, maravilhosa solução.

Funcionou muito bem! Eu não sabia que podíamos usar expressões regulares en
uma condição, como também, nem sabia da existência do || para indicar um
início de uma função.
Agradeço imensamente a ajuda e vou ler o link indicado pelo Paulo.

Bom dia a todos.
Post by ***@yahoo.com.br [shell-script]
Olá Mestre Julio, vc tem razão, falta um espaço ali :) às vezes os emails
da lista
vem com fonte monoespaçada e às vezes não, pra pegar esses detalhes sem fonte
monoespaçada é uma dificuldade. (sem contar que a indentação também vai
pro espaço)
Abraços Paulo
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Ednei,
[[ ... ]] é um cmd e como tal, deve ter um espaço em branco os separando
de cada um dos operandos que estão no
Post by Rodrigo Cunha ***@gmail.com [shell-script]
seu interior, pois eles são os parâmetros que vc está passando para o
cmd test.
Post by Rodrigo Cunha ***@gmail.com [shell-script]
No código que vc mandou me pareceu não haver espaços antes dos ]], em
duas linhas.
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Abcs,
Julio
*
Próximos cursos de Shell*
*Cidade LocalPeríodo*
*
​
**São Paulo 4Linux <https://www.4linux.com.br/
curso/programacao-em-shell-script>05
Post by Rodrigo Cunha ***@gmail.com [shell-script]
*-09/12*
***
Dou treinamento de /Shell/em qualquer cidade.
Em 21 de setembro de 2016 09:48, Édnei Rodrigues
__
Obrigado pela sugestão!
É bem interessante a proposta.
-rwxr-xr-x 1 rluser radiantlogic 249 Sep 21 09:33 status_connector.sh
./status_connector.sh: line 6: unexpected token `newline', conditional
binary operator expected
Post by Rodrigo Cunha ***@gmail.com [shell-script]
./status_connector.sh: line 6: syntax error near `{'
./status_connector.sh: line 6: ` {'
#!/bin/bash
cat listas_conectores.txt | while read linha;
do
[[ "$linha" =~ ^$]] ||
{
if [[ "$linha" =~ ^\.]]; then
top_nome="${linha#.}"
continue
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi;}
done
bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.
html
Post by Rodrigo Cunha ***@gmail.com [shell-script]
<http://gnu.org/licenses/gpl.html>>
O que significa aquele || ?
__
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o
du Unix), ele não reconhece
Post by Rodrigo Cunha ***@gmail.com [shell-script]
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}
export -f funcao
__
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não
reconhecia função,
Post by Rodrigo Cunha ***@gmail.com [shell-script]
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou
2 pra trás.
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar
comandos assim, e em puro bash
Post by Rodrigo Cunha ***@gmail.com [shell-script]
vai direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está
usando, pois o Paulo usou
Post by Rodrigo Cunha ***@gmail.com [shell-script]
recursos recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os
recursos sugeridos podem
Post by Rodrigo Cunha ***@gmail.com [shell-script]
não funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou
"grep".
Post by Rodrigo Cunha ***@gmail.com [shell-script]
Post by ***@yahoo.com.br [shell-script]
E além de tudo usando esse recursos built-in's, em epecial do Bash há
um ganho de performance
Post by Rodrigo Cunha ***@gmail.com [shell-script]
sem comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
----------------------------------------------------------
----------------------------------------------------------
itamarnet@yahoo.com.br [shell-script]
2016-09-21 21:40:01 UTC
Permalink
Édnei

estranho que minha mensagem anterior ter extraviado, mas vou repeti-la, as vezes o yahoo parece perder mensagens.


Os pipes justapostos ( || ) não indicam função, mas é um desvio de fluxo dos comandos em seu script, assim como em programação:
Os pipes juntos ||, equivalem a "OR"
E os "E comerciais" && equivalem ao "AND"


Exemplo:
$ a=1
$ test $a = 1 && echo "O valor é 1" || echo "O valor NÃO é 1".


E se precisar de mais de uma comando numa das situações o englobamos entre chaves, como


$ a= 1
$ teste $a = 1 && echo "O valor é 1" || { echo "O valor NÃO é 1"; echo "O valor é $a"; }


Ajudou a esclarecer?


[]'s
Itamar
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-21 21:43:45 UTC
Permalink
Obrigado pela resposta.

Certo, então é o 'or' que conheço. Porém, confundiu minha cabeça, por que
temos um if test ou uma função? Qual é a lógica que esta sendo testada ?

Obrigado.
Post by ***@yahoo.com.br [shell-script]
Édnei
estranho que minha mensagem anterior ter extraviado, mas vou repeti-la, as
vezes o yahoo parece perder mensagens.
Os pipes justapostos ( || ) não indicam função, mas é um desvio de fluxo
Os pipes juntos ||, equivalem a "OR"
E os "E comerciais" && equivalem ao "AND"
$ a=1
$ test $a = 1 && echo "O valor é 1" || echo "O valor NÃO é 1".
E se precisar de mais de uma comando numa das situações o englobamos entre
chaves, como
$ a= 1
$ teste $a = 1 && echo "O valor é 1" || { echo "O valor NÃO é 1"; echo "O
valor é $a"; }
Ajudou a esclarecer?
[]'s
Itamar
itamarnet@yahoo.com.br [shell-script]
2016-09-21 22:05:41 UTC
Permalink
Édnei


A forma como o if funciona em shell difere como em programas em geral, pois ele não testa uma condição, mas o código de retorno. Voltando ao exemplo simplista anterior que forneci, se estivesse num script seria assim

a=1
if test $a = 1
then
echo "O valor é 1"
else
echo "O valor NÃO é 1"
fi


nesse caso o if testou o código de retorno da comando test, que no caso retornou 0.


Outro exemplo
if grep 'texto' arquivo.txt >/dev/null
then
echo "Encontrada a palavra texto"
fi


Se houver a palavra texto dentro do arquivo.txt a mensagem será ecoada.
Note que o comando grep foi desviado para /dev/null para não mostrar a sua saída e o if apenas analisou se teve êxito na procura.


Poderia ter usado "grep -q" para que o grep não ecoe, mas nem todas as versões do grep possuem essa opção.


[]'s
Itamar
itamarnet@yahoo.com.br [shell-script]
2016-09-21 22:26:34 UTC
Permalink
Édnei
para ser didático e referenciando o script do Paulo, seria:




# Esse é o Loop primário
while read linha do
# Aqui ele faz o test mais avançado usando [[ condição ]]
# Se o teste funcionar ele nem executa o bloco que possue o if e está dentro do bloco nas chaves
# Mas se o teste falhar esse bloco é executado
# Nesse caso testa se é uma linha vazia, se não for executa o bloco
[[ "$linha" =~ ^$ ]] || {
# Nesse caso aqui, é parecido, testa se alinha começa com ponto
# Se funcionar define a variável e pula para o próximo elemento do laço primário
if [[ "$linha" =~ ^\. ]]
then
top_nome="${linha#.}"
continue
# Se falhar, aqui mostra o comando usando o topology.sh e seus argumentos
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi
}
done <topologias-conectores.txt



Pegou a jogada?


[]'s
Itamar
Édnei Rodrigues ednei.felipe.rodrigues@gmail.com [shell-script]
2016-09-21 23:35:43 UTC
Permalink
Bah, melhor explicação impossível. Obrigado!
Post by ***@yahoo.com.br [shell-script]
Édnei
# Esse é o Loop primário
while read linha
do
# Aqui ele faz o test mais avançado usando [[ condição ]]
# Se o teste funcionar ele nem executa o bloco que possue o if e está
dentro do bloco nas chaves
# Mas se o teste falhar esse bloco é executado
# Nesse caso testa se é uma linha vazia, se não for executa o bloco
[[ "$linha" =~ ^$ ]] || {
# Nesse caso aqui, é parecido, testa se alinha começa com ponto
# Se funcionar define a variável e pula para o próximo elemento do
laço primário
if [[ "$linha" =~ ^\. ]]
then
top_nome="${linha#.}"
continue
# Se falhar, aqui mostra o comando usando o topology.sh e seus argumentos
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi
}
done <topologias-conectores.txt
Pegou a jogada?
[]'s
Itamar
phfbettega@yahoo.com.br [shell-script]
2016-09-21 13:28:43 UTC
Permalink
Deve ser porque '||' e '{' tem que ficar na mesma linha. Se vc quiser separar tem que colocar
uma contrabarra e logo depois dar <enter>.
A contrabarra funciona como escape do <enter>, é como se fosse tudo uma linha só.

ou isso
[[ "$linha" =~ ^$]] || {

ou isso
[[ "$linha" =~ ^$]] || \
{


Sobre o ||
http://wiki.softwarelivre.org/TWikiBar/TWikiBarPapo004#Querida_Encolheram_o_Comando_Con
Abraços Paulo Bettega

ps- Sobre o uso do sed, só consegui pensar no sed alimentando o loop
e não o contrário, colocar o sed no meio do loop.
É praticamente uma tradução em sed do que eu propus em bash.

sed -nr '/^\./ {s/\.(.*)/\1/;h;n};/^[A-Z]/ {G;s/.*: (.*)\n(.*)/\2 \1/p}' listas_conectores.txt|
while read linha;do echo topology.sh printConnectorStatus $linha;done

A princípio eu achei que usar o ponto no começo da linha ia ser um problema, mas no fim
das contas ficou um ótimo delimitador. Inclusive não importa se há linhas vazias entre todas as
linhas ou apenas separando os blocos.
Post by Édnei Rodrigues ***@gmail.com [shell-script]
Obrigado pela sugestão!
É bem interessante a proposta.
-rwxr-xr-x 1 rluser radiantlogic 249 Sep 21 09:33 status_connector.sh
./status_connector.sh: line 6: unexpected token `newline', conditional binary operator expected
./status_connector.sh: line 6: syntax error near `{'
./status_connector.sh: line 6: ` {'
#!/bin/bash
cat listas_conectores.txt | while read linha;
do
[[ "$linha" =~ ^$]] ||
{
if [[ "$linha" =~ ^\.]]; then
top_nome="${linha#.}"
continue
else
echo "topology.sh printConnectorStatus $top_nome ${linha#*:}"
fi;}
done
bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
O que significa aquele || ?
__
Se vc estiver usando Bourne Shell, o sh (mas não é esse sh do Linux, é o du Unix), ele não reconhece
funtion funcao
{
...
}
Reconhece somente com a sintaxe
funcao ()
{
...
}
export -f funcao
__
Olá Itamar, valeu o feedback :)
É verdade, vc tem razão, não pensei na portabilidade.
Se for um shell com menos recursos acho que a solução seria
isolar o bloco com sed e pegar as informações com grep, ou usar
awk direto que faz o serviço dos dois.
Um tempo atrás teve uma dúvida na lista sobre um shell que não reconhecia função,
devia ser um dos shells do busybox.
Esse é um exercício e tanto, fazer os scripts compatíveis com bash 3 ou 2 pra trás.
Abraços Paulo
Post by ***@yahoo.com.br [shell-script]
A solução do Paulo é perfeita.
Simples e objetiva e atende o que deseja pela sua descrição.
Para o que vc deseja o Sed acredito não ter suporte para executar comandos assim, e em puro bash vai
direto ao
Post by ***@yahoo.com.br [shell-script]
ponto.
A única ressalva que faço é verificar a versão do Shell que está usando, pois o Paulo usou recursos
recentes e
Post by ***@yahoo.com.br [shell-script]
dependendo da empresa, essa atualização pode ser negligenciada, e os recursos sugeridos podem não
funcionar da
Post by ***@yahoo.com.br [shell-script]
forma como estão, mas é possível trocar por uso de "test", "sed" ou "grep".
E além de tudo usando esse recursos built-in's, em epecial do Bash há um ganho de performance sem
comparação.
Post by ***@yahoo.com.br [shell-script]
[]'s
Itamar
----------------------------------------------------------
----------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
Continue reading on narkive:
Loading...