Fórum Ubuntu Linux - PT

Suporte Técnico => Programação e Scripts => Tópico iniciado por: sigur em 30 de Maio de 2012, 16:37

Título: [resolvido] comando sed
Enviado por: sigur em 30 de Maio de 2012, 16:37
Pessoal, tentei adaptar um modelo de uso do sed, que encontrei aqui, para comentar uma linha de um arquivo, mas não estou conseguindo.

Pois bem, quero comentar todas as linhas do meu arquivo TeX que começam com \usepackage.

O problema é que não consigo fazer a troca, ou melhor, inserir o símbolo % na frente destas linhas, pois eu acho que a barra e o % precisar ser passados de modo diferente.

Tentei
Código: [Selecionar]
sed /\usepackage/%\usepackage/ 1.tex > 2.tex mas o erro foi
Código: [Selecionar]
sed: -e expressão #1, caractere 12: comando desconhecido: `%'
alguma ajuda?
Em resumo, preciso inserir % em vários arquivos TeX nas linhas que começam com \usepackage

Obrigado.
Título: Re: comando sed
Enviado por: irtigor em 30 de Maio de 2012, 17:08
Código: [Selecionar]
sed 's;^\\usepackage;%\\usepackage;' 1.tex
Substitui linhas que começam com \usepackage por %\usepackage. Você pode usar a opção "-i/--in-place" pra substituir diretamente.
Título: Re: comando sed
Enviado por: sigur em 30 de Maio de 2012, 21:20
Código: [Selecionar]
sed 's;^\\usepackage;%\\usepackage;' 1.tex
Substitui linhas que começam com \usepackage por %\usepackage. Você pode usar a opção "-i/--in-place" pra substituir diretamente.

perfeito!!

muito obrigado. O que quer dizer com 'substituir diretamente'?

Só mais uma pergunta: se eu quiser fazer mais de uma substituição no mesmo arquivo, por exemplo, comentar também as linhas que começam com \title, posso fazer como? tentei fazer
Código: [Selecionar]
sed 's;^\\usepackage;%\\usepackage;' 's;^\\title;%\\title;' 1.tex mas não deu.

Tentei
Código: [Selecionar]
sed 's;^\\usepackage;%\\usepackage;'  1.tex | sed 's;^\\title;%\\title;' > 2.tex mas não deu

Será que terei que criar um .sh e inserir um monte de linhas, uma para cada comando sed trocando as coisas?

Obrigado mais uma vez. Já ajudou bem.
Título: Re: comando sed
Enviado por: irtigor em 30 de Maio de 2012, 22:11
Código: [Selecionar]
sed -e 's;^\\usepackage;%\\usepackage;' -e 's;^\\title;%\\title;' 1.tex
Com um "-i" o arquivo 1.tex seria modificado, no lugar do resultado aparecer na saída padrão.
Título: Re: comando sed
Enviado por: sigur em 30 de Maio de 2012, 22:21
Código: [Selecionar]
sed -e 's;^\\usepackage;%\\usepackage;' -e 's;^\\title;%\\title;' 1.tex
Com um "-i" o arquivo 1.tex seria modificado, no lugar do resultado aparecer na saída padrão.

ah, entendi. então ele altera e escreve no próprio arquivo? é como se fosse mexer em 1.tex e mandar a saída pro próprio 1.tex?

eu havia tentado colocar 1.tex > 1.tex no fim do comando, mas o resultado ficou um arquivo em branco.
daí eu fiz uma gambiarra. Veja o que eu fiz:
Código: [Selecionar]
cat texfiles/comm*.tex > tudo.tex
sed 's;^\\documentclass;%\\documentclass;' tudo.tex > temp.tex
mv temp.tex tudo.tex
sed 's;^\\usepackage;%\\usepackage;' tudo.tex > temp.tex
mv temp.tex tudo.tex
sed 's;^\\begin{document};%\\begin{document};' tudo.tex > temp.tex
mv temp.tex tudo.tex
sed 's;^\\end{document};%\\end{document};' tudo.tex > temp.tex
mv temp.tex comm.tex
rm tudo.tex

Deu certo, mas não ficou nem um pouco legal.

Agora vou tentar sua dia.
Mais uma vez, obrigado.
Título: Re: comando sed
Enviado por: irtigor em 31 de Maio de 2012, 08:39
http://wiki.bash-hackers.org/howto/redirection_tutorial#why_sed_sfoobarfile_file_doesn_t_work
Título: Re: comando sed
Enviado por: sigur em 31 de Maio de 2012, 09:49
http://wiki.bash-hackers.org/howto/redirection_tutorial#why_sed_sfoobarfile_file_doesn_t_work

muito bom. consegui usar suas dicas e colocar um monte de subs. no mesmo comando. agora é só executar o .sh e partir pro abraço.

Valeu hein.
Título: Re: comando sed
Enviado por: sigur em 31 de Maio de 2012, 21:08
Opa, eu novamente.

Não estou tendo tanto sucesso pra compilar tudo de uma vez. Mas isso é detalhe. Portanto, estou querendo fazer o seguinte:

para cada arquivo .tex dentro de uma pasta, queria copiar as linhas que começam com \title e com \author, copia-las nesta ordem, para um outro arquivo.

Tentei usar o cat 1.tex | grep \title  mas o problema é que ele retorna também as linhas que começam com \maketitle. Não sei porque, mas ele não segue fielmente a palavra.

A outra dificuldade é fazer buscar, para um mesmo arquivo, as duas linhas de uma vez.

Será que dá pra fazer um .sh?
Valeu.
Título: Re: comando sed
Enviado por: irtigor em 31 de Maio de 2012, 23:59
A contra barra é um carácter de escape (http://wiki.bash-hackers.org/syntax/quoting#quotes_and_escaping). Use
Código: [Selecionar]
grep -E '(^\\title|^\\author)' arquivo.tex
Título: Re: comando sed
Enviado por: sigur em 01 de Junho de 2012, 12:58
A contra barra é um carácter de escape (http://wiki.bash-hackers.org/syntax/quoting#quotes_and_escaping). Use
Código: [Selecionar]
grep -E '(^\\title|^\\author)' arquivo.tex

opa, legal. Obrigado.
Veja como está ficando:

Código: [Selecionar]
for file in texfiles/*.tex; do
sed -e 's;\\maketitle;\\maketitle\\thispagestyle{empty}\\pagestyle{empty};'  -i $file
done

Código: [Selecionar]
rm indice-comm.tex # dá erro se o file não existe. queria colocar um if
for file in texfiles/comm*.tex ; do
grep -E '^.title|^.author' $file >> indice-comm.tex # trocar pela sua sugestão
echo -e " " >>  indice-comm.tex # gambiarra pra pular linha no arquivo
sed -e 's;^\\title;\\titulo;' -e 's;^\\author;\\autor;' -i indice-comm.tex
done

# compilar em pdf os comm*.tex da pasta texfiles
for file in texfiles/comm*.tex; do
pdflatex $file
pdflatex $file
mv comm*.pdf pdffiles/
done

rm *.aux
rm *.log
#rm *.out

# juntar todos os comm*.pdf em um arquivo só
# chamado resumos-comm.pdf
pdftk pdffiles/comm*.pdf cat output resumos-comm.pdf

Título: Re: comando sed
Enviado por: sigur em 07 de Junho de 2012, 22:23
Pessoal, queria fazer um teste para saber se existe algum arquivo no diretório com extensão .log ou .aux. Caso sim, queria redeltar todos eles.

Tentei fazer
Código: [Selecionar]
if [ -f *.aux ];
then
rm *.aux
rm *.log
else
echo "nao tem nenhum aux"
fi
mas aparece o erro
Código: [Selecionar]
./lista.sh: linha 9: [: número excessivo de argumentos

Alguma ajuda?
Título: Re: comando sed
Enviado por: irtigor em 07 de Junho de 2012, 23:18
"-f" testa se 1 arquivo é normal. Se no diretório tem 1.aux e 2.aux, *.aux vai ser expandido para esses dois, então vai ficar [ -f 1.aux 2.aux ] o que é errado.

Você pode usar um loop ou remover de qualquer forma, redirecionando o stderr pra /dev/null.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 09:31
"-f" testa se 1 arquivo é normal. Se no diretório tem 1.aux e 2.aux, *.aux vai ser expandido para esses dois, então vai ficar [ -f 1.aux 2.aux ] o que é errado.

Você pode usar um loop ou remover de qualquer forma, redirecionando o stderr pra /dev/null.

Hum, entendi o uso do -f.

Quando você diz para usar um loop, seria um for? Mas como saber se existem arquivos .aux na pasta, para que o rm dentro do for não dê erro?

Veja se entendi: essa parte do null seria para mandar a msg de erro pra lá? Lembro de ter lido algo assim. Então, se eu fizer apenas
Código: [Selecionar]
rm *.aux > /dev/null sempre dará certo, pois não verei msg de erros na tela? Se tiver erros, isso deixará mais lento a execução?

Valeu por enquanto.
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 10:41
Código: [Selecionar]
for i in *.aux; do
   [[ -f "$i" ]] || continue
   rm "$i"
done

Código: [Selecionar]
rm *.aux 2> /dev/null
[[ $? -eq 1 ]] && echo "nao tem nenhum aux"

O segundo deve ser mais rápido porque pega todos os arquivos de uma só vez, enquanto o outro trabalha em série.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 10:55
Opa, legal hein. Valeu pela ajuda.

Só não entendi muito o porque de dois [[.

Mas está ficando show de bola.
Obrigado.
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 11:20
É um comando de teste embutido no bash (adotado do ksh e presente no zsh também), é mais robusto que o "[" (dá pra fazer comparação com expressão regular, por exemplo).

Se o seu script vai depender do bash, eu não vejo motivos pra não usá-lo.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 11:58
Bem, acho que estou terminando. Está ficando legal. Optei por não exibir a saída do pdflatex, pois gera muita coisa na tela. Só que se der erro, daí trava tudo.

Aconteceu agora pouco. Havia um erro dentro do .tex, erro de TeX mesmo, comando errado. Daí o script parou e eu não consegui finalizar. Tive que fechar a janela do terminal.

Veja como está ficando:
Código: [Selecionar]
## generate list of tex files to use with \import command
#rm *.aux 2> /dev/null
#[[ $? -eq 1 ]] && echo "nao tem nenhum aux"
#for i in *.aux; do
#   [[ -f "$i" ]] || continue
#   rm "$i"
#done

echo  "| ###########################"
echo "| removendo arquivos temporários para inciar processo..."
rm texfiles/*.aux 2> /dev/null
rm *.aux 2> /dev/null
rm *.log 2> /dev/null
rm *.toc 2> /dev/null

echo "| removendo arquivos antigos de índice para importação..."
rm indice-*.tex 2> /dev/null

#if [ -f indice-comm.tex ];
#then
#rm indice-comm.tex
#fi

echo "| criando arquivos novos de índice para importação..."
for file in texfiles/comm*.tex ; do
#grep -E '^.title|^.author' $file >> indice-comm.tex
echo -e "\\import{$file}\n" >>  indice-comm.tex
sed -e 's;\.tex;;' -i indice-comm.tex
done
echo "| arquivo indice-comm.tex criado"

#if [ -f indice-talk.tex ];
#then
#rm indice-talk.tex
#fi

for file in texfiles/talk*.tex ; do
#grep -E '^.title|^.author' $file >> indice-talk.tex
echo -e "\\import{$file}\n" >>  indice-talk.tex
sed -e 's;\.tex;;' -i indice-talk.tex
done
echo "| arquivo indice-talk.tex criado"

#if [ -f indice-poster.tex ];
#then
#rm indice-poster.tex
#fi

for file in texfiles/poster*.tex ; do
#grep -E '^.title|^.author' $file >> indice-poster.tex
echo -e "\\import{$file}\n" >>  indice-poster.tex
sed -e 's;\.tex;;' -i indice-poster.tex
done
echo "| arquivo indice-poster.tex criado"

echo "|"
echo "| compilando caderno.tex duas vezes com pdflatex..."
echo "| ..."
echo "| ..."
pdflatex caderno.tex 1> /dev/null
pdflatex caderno.tex 1> /dev/null
echo "| arquivo caderno.pdf criado"
echo "| "
echo "| removendo arquivos temporários para finalizar processo..."
rm texfiles/*.aux 2> /dev/null
rm *.aux 2> /dev/null
rm *.log 2> /dev/null
rm *.toc 2> /dev/null
echo "| PRONTO!"
echo  "| ###########################"
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 13:09
Você pode colocar uma cadeia condicional, tipo

Código: [Selecionar]
pdflatex caderno.tex 1> /dev/null || exit $?

Se o pdflatex falhar (código de estado diferente de 0) o comado exit é executado. Também dê uma olhada no trap.

No lugar de fechar o terminal, você pode apertar ctrl+c pra finalizar o programa em execução no primeiro plano.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 13:34
Você pode colocar uma cadeia condicional, tipo

Código: [Selecionar]
pdflatex caderno.tex 1> /dev/null || exit $?

Se o pdflatex falhar (código de estado diferente de 0) o comado exit é executado. Também dê uma olhada no trap.

No lugar de fechar o terminal, você pode apertar ctrl+c pra finalizar o programa em execução no primeiro plano.

hum, não deu certo. coloquei um comando \aleph no meu caderno.tex, de modo que o pdflatex irá reclamar, pois não usei $\aleph$ (não sei se você usa tex). Mas o problema foi o mesmo, parou e nada. Apertei ctrl+c mas não deu, só imprimiu no terminal ^C, ou seja, tem algo estranho.

Talvez seja o modo de como o pdflatex trabalha. Na verdade, quando encontra um erro no tex, ele para e espera o user tomar uma atitude. Rodando pdflatex direto pelo terminal, o erro é
Código: [Selecionar]
! Missing $ inserted.
<inserted text>
                $
l.527 \aleph
           
?

ou seja, a execução para. Para interromper, posso usar x <enter> e daí volto pro prompt.
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 14:10
Olhei o manual, se você usar a opção "-halt-on-error" o que eu falei deve funcionar.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 14:20
Olhei o manual, se você usar a opção "-halt-on-error" o que eu falei deve funcionar.

Opa! Perfeito. Forcei um erro e agora ele não trava. O processo do pdflatex vai até o fim, com as consequências de se ter um erro, claro. Mas o script termina e volta pro prompt.

Só preciso arrumar um modo de fazer algo aparecer na tela, dizendo que o processo foi interrompido, pois as msg estão sendo as mesmas, dando a impressão de que tudo está certo.

Será que tem como testar se a saída de erros do pdflatex é vazia ou não? Não sei se funciona como no comando cp, por exemplo, onde mostra na tela uma msg de erro quando não copia.

Vou fuçar um pouco. Mas uma coisa é certa: se eu pedir pra deletar o pdf logo de cara, se der erro não será criado um pdf, daí eu sei que tem problema, mesmo as msg sendo as mesmas.

Valeu!
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 14:32
A variável $? guarda o ultimo sinal. "0" significa que o programa rodou certo, os outros números indicam os vários tipos de erros (depende do programa). Uma versão modificada do que eu já havia mostrado:

Código: [Selecionar]
rm *.aux &> /dev/null
[[ $? -eq 0 ]] && echo "Tudo removido com sucesso" || echo "Um erro ocorreu, saida do rm=$?"
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 14:36
A variável $? guarda o ultimo sinal. "0" significa que o programa rodou certo, os outros números indicam os vários tipos de erros (depende do programa). Uma versão modificada do que eu já havia mostrado:

Código: [Selecionar]
rm *.aux [b]&>[/b] /dev/null
[[ $? -eq 0 ]] && echo "Tudo removido com sucesso" || echo "Um erro ocorreu, saida do rm=$?"

é para ser & ou é 2, como nos outros casos? Vou testar. Não sei se os erros do pdflatex são como os dos comandos do bash. Preciso dar uma saída, mas assim que voltar, eu testo.
Valeu mesmo hein.
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 14:46
Tanto faz, eu coloquei "&" pra redirecionar tanto o stdout quanto o stderr (com "2" só redireciona o stderr).
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 21:41
Olá. Não está fácil de arrumar. Forcei um erro no .tex e ao compilar direto pelo terminal, obtive
Código: [Selecionar]
pdflatex -halt-on-error caderno.tex
! Missing $ inserted.
<inserted text>
                $
l.358 x^
        2
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on caderno.log.

Pois bem, tentei redirecionar o erro para um arquivo com
Código: [Selecionar]
pdflatex -halt-on-error caderno.tex 2> blamas o arquivo bla ficou vazio, ou seja, acho que a variável $? que você falou não é usada pelo pdflatex.

Talvez exista algum comando que pause o script caso ocorra algum erro?

Obrigado.
Título: Re: comando sed
Enviado por: irtigor em 08 de Junho de 2012, 21:50
Todos os programas fornecem retorno, o que pode acontecer é dele não ser certo (por ex. sempre voltar 0, mesmo com erro). Teste
Código: [Selecionar]
pdflatex -halt-on-error arquivo_com_erro.tex
echo $?
pdflatex -halt-on-error arquivo_sem_erro.tex
echo $?

Se o retorno for correto, é só criar uma estrutura de desvio (um if).

----
Vale frisar que a variável $? guarda o retorno do ultimo programa executado.
Título: Re: comando sed
Enviado por: sigur em 08 de Junho de 2012, 22:08
Que interessante!

Com erro, voltou 1.
Sem erro, voltou 0.

Vou fazer mais testes. Valeu.

Opa. Perfeito. Veja como ficou a parte pra compilar:
Código: [Selecionar]
pdflatex -halt-on-error caderno.tex 1> /dev/null
[[ $? -eq 1 ]] && echo "| Erro no pdflatex. Verifique os arquivos TeX." && exit
pdflatex -halt-on-error caderno.tex 1> /dev/null
echo "| arquivo caderno.pdf criado"

Se der erro, avisa na tela e para. Caso não tenha erro, compila mais uma vez.
Muito bom. Agora posso descansar.
Bom fim de semana irtigor.
Título: Re: comando sed
Enviado por: sigur em 13 de Junho de 2012, 21:05
Prezado colega irtigor, aqui estou mais uma vez para tentar melhorar meu script.

Pois bem, meus arquivos são criados baseados nos arquivos .tex de uma pasta. Esses arquivos não estão nomeados com os nomes dos usuários, mas sim, com os  e-mails. Portanto, quando uso
Código: [Selecionar]
echo "| criando arquivos novos de índice para importação..."
for file in texfiles/comm*.tex ; do
#grep -E '^.author' $file >> indice-comm.tex
echo -e "\\import{$file}\n" >>  indice-comm.tex
sed -e 's;\.tex;;' -i indice-comm.tex
done
echo "| arquivo indice-comm.tex criado"
o resultado não fica por ordem alfabética baseado nos nomes dos users.

Bem, mas dentro de cada arquivo .tex existe o comando \author{} que contém o nome completo de cada user. Então, minha ideia é tentar recuperar essa informação para usá-la na ordenação.

Veja que acima eu fiz um teste com o grep de modo consegui escrever no indice-comm duas linhas para cada $file:
uma com o \author{} e a outra com o \import{$file}. Só que isso não ajuda, pois como vou pedir pra colocar o indice-comm em ordem alfabética? Sei que tem o comando sort, mas daí ele vai colocar tudo o que for \author na frente, vai deixar o \import pro fim, perdendo a relação entre eles.

Acho que dá pra corrigir se eu conseguir escrever essas duas informações na mesma linha do indice-comm. Mas isso eu não sei fazer. Queria escrever no arquivo algo parecido com:
Código: [Selecionar]
\author{fulano}\import{arquivo}
\author{outro fulano}\import{seu outro arquivo}
e depois classificar alfabeticamente este arquivo.

Alguma ideia mais formal? Obrigado desde já.
Título: Re: comando sed
Enviado por: irtigor em 13 de Junho de 2012, 22:01
Em bash você pode fazer algo assim
Código: [Selecionar]
i=0
while read linha; do
   (( $i%2 == 0 )) && echo -n "\\$linha" || echo "\\$linha"
   let i=$i+1
done < indice-comm.tex > indice-comm-final.tex

Recebe como entrada (indice-comm.tex)
Código: [Selecionar]
\author{fulano}
\import{arquivo}
\author{outro fulano}
\import{seu outro arquivo}

Produz (indice-comm-final.tex)
Código: [Selecionar]
\author{fulano}\import{arquivo}
\author{outro fulano}\import{seu outro arquivo}

O unico problema é que não vai ler linhas sem terminador ('\n'), mas isso só é possível na ultima linha, se ela não aparecer coloque (antes do loop)
Código: [Selecionar]
echo -n '\n' >> indice-comm.tex

----
A contra barra da variável some, adicionei uma ao echo.
Título: Re: comando sed
Enviado por: sigur em 14 de Junho de 2012, 08:48
@irtigor, muito obrigado. Ficou perfeito. Entendi mais ou menos o que os comandos fazem. Como quero deixar tudo sempre no mesmo arquivo e não sei se dá pra fazer o input igual ao output, fiz uma gambiarra. Veja:
Código: [Selecionar]
i=0
while read linha; do
   (( $i%2 == 0 )) && echo -n "\\$linha" || echo "\\$linha"
   let i=$i+1
done < indice-comm.tex > temp.tex
sort temp.tex > indice-comm.tex

Deu certinho. Ficou legal.

Como temos arquivos que chamam indice-comm.tex e indice-talk.tex e indice-poster.tex, acabei fazendo 3 vezes as mesmas coisas, sempre trocando o final dos arquivos em questão.

Pergunta: tem como fazer um laço, algo do tipo: para tipo em {comm,talk,poster} do e daí faço os comandos uma vez só, dentro do laço, usando como fonte os arquivos indice-$tipo.tex?

Mais uma vez, obrigado. Ficou perfeito.
Título: Re: comando sed
Enviado por: irtigor em 14 de Junho de 2012, 08:59
Expansão de chaves
Código: [Selecionar]
for i in indice-{comm,talk,poster}.tex; do
  # use o "$i"
done

Três voltas, i assume os valores: indice-comm.tex, indice-talk.tex e indice-poster.tex. Pra pegar só a diferença, vai ter que usar manipulação de string.

----
Não tem como a entrada ser igual a saída, o redirecionamento é criado antes, portanto a arquivo ficaria truncado.
Título: Re: comando sed
Enviado por: sigur em 14 de Junho de 2012, 10:59
Opa. Está quase tudo certo. Percebi que tem algo errado com a paginação do pdf gerado no fim. Por algum motivo, o número de página inserido não corresponde ao número real.

Isso só ocorre se compilo com o script. Usando o pdflatex direto no terminal, tudo funciona. Pensei que fosse algum problema em deletar os aux, mas não sei. Já comentei e continua na mesma.

Fuçando nos arquivos indice-* criados, notei coisas estranhas. Por exemplo, depois de colocar as linhas do \import{} na frente das linhas do \author{}, um deles ficou com
Código: [Selecionar]
\bla{xxx}^M\import{zzzz} ou seja, aparece um ^M.

Também, alguns arquivos possuem dois comandos \author{} em linhas consecutivas. Daí, o \author subiu só em uma delas e o \import ficou, ao invés de ficar com  
Código: [Selecionar]
\author{xxx}\author{www}\import{zzzz}
Estranho! Acho que terei que editar a fonte para tirar essa duplicidade.



não tem como fazer uma busca com o grep e fazer a troca de um comando e logo na frente usar o echo para escrever o nome do arquivo e salvar tudo isso em um file com o uso do > ? Algo do tipo
Código: [Selecionar]
grep 'bla' foo | sed 's/bla/mmm/'  [b]E[/b] echo '$file' > file.tex

Qual a diferença entre echo ' ' e echo " " ?
Título: Re: comando sed
Enviado por: irtigor em 14 de Junho de 2012, 14:19
http://wiki.bash-hackers.org/syntax/quoting#quotes_and_escaping

Com sed
Código: [Selecionar]
sed -i '/baz/s/foo/bar/' file.txt

Substitui foo por bar, somente nas linhas com baz.
Título: Re: comando sed
Enviado por: sigur em 14 de Junho de 2012, 14:25
Estou tentando guardar os comandos em duas variáveis, para usar o echo e já colocar uma na frente da outra. Mas se eu digitar tudo no terminal, como abaixo, deu certinho. Porém, usando o .sh não funciona, a saída fica com 3 linhas, mas vazias.

Tudo no terminal:
Código: [Selecionar]
for file in texfiles/comm1*.tex; do autor=$(grep -E '^.author' $file); arquivo=$(echo -e "\\import{$file}"); echo $autor$arquivo >> indice-comm.tex; done

Bloco do .sh
Código: [Selecionar]
echo "| criando arquivos novos de índice para importação..."
for file in texfiles/comm*.tex ; do
autor = $( grep -E '^.author' $file ) #| sed -e 's;\\author;\\bla;' ); #>> indice-comm.tex
arquivo = $( echo -e "\\import{$file}" ) #| sed -e 's;\.tex;;' ); #>> indice-comm.tex
echo $autor$arquivo >> indice-comm.tex
done

nesse dá erro:
Código: [Selecionar]
./criar-caderno.sh: linha 25: autor: comando não encontrado
./criar-caderno.sh: linha 26: arquivo: comando não encontrado
./criar-caderno.sh: linha 25: autor: comando não encontrado
./criar-caderno.sh: linha 26: arquivo: comando não encontrado
./criar-caderno.sh: linha 25: autor: comando não encontrado
./criar-caderno.sh: linha 26: arquivo: comando não encontrado

Não entendo o uso de ponto-vírgula.

Obrigado.
Título: Re: comando sed
Enviado por: irtigor em 14 de Junho de 2012, 14:54
Código: [Selecionar]
for file in texfiles/comm*.tex ; do
  autor="$(grep -E '^\\author' "$file")"
  echo "$autor\\import{$file}" >> indice-comm.tex
done
Usar um subshell pra um echo não é uma boa ideia.

-----
Uma alteração, no exemplo anterior não usei o -r do read, assim é melhor

Código: [Selecionar]
i=0
while read -r linha; do
   (( $i%2 == 0 )) && echo -n "$linha" || echo "$linha"
   let i=$i+1
done < indice-comm.tex > temp.tex
sort temp.tex > indice-comm.tex
Título: Re: comando sed
Enviado por: sigur em 14 de Junho de 2012, 19:37
Prezado colega. Muito obrigado pela ajuda e desculpe por fazê-lo trabalhar demais. Conforme fui estudando, percebi que podia fazer mais simples, ou seja, já pude escrever no arquivo uma linha na frente da outra, ou melhor, os dois comandos na mesma linha. Daí, não precisei da gambiarra pra juntar duas linhas.

Pois bem, agora acho que está tudo redondo, consertei o problema da paginação. Só não sei porque motivo algumas linhas do \import não juntaram. Mas tudo bem, pro TeX não tem problema, o importante é usar o sort.

Veja como ficou o bloco
Código: [Selecionar]
echo "| criando arquivos novos de índice para importação..."
for file in texfiles/comm*.tex ; do
  autor="$(grep -E '^\\author' "$file" | sed -e 's;\\author;\\bla;' )"
  echo "$autor\\import{$file}" >> temp.tex
  sed -e 's;\.tex;;' -i temp.tex
done
sort temp.tex > indice-comm.tex
rm temp.tex 2> /dev/null
echo "| arquivo indice-comm.tex criado"

Troquei o \author por \bla pois não posso ter mais de um no mesmo arquivo tex. Daí, defini o \bla como vazio e pronto.

Obrigado mesmo pela ajuda hein.
Valeu.