Use sed para formatar parágrafos para látex

1

Estou usando sed para reformatar muitos arquivos de texto simples a serem compilados com o LaTeX. O arquivo contém várias seções com palavras-chave que fornecem um intervalo. Uma dessas seções com as quais estou trabalhando é para hinos. Um hino começa com a palavra-chave Hymn e termina com a palavra Amen. O texto do hino deve ser formatado para um contexto de "verso".

Aqui está um arquivo de entrada de amostra:

Hymn I
Conditor alme siderum,
Aeterna lux credentium,
Christe, redemptor omnium,
Exaudi preces supplicum.

Qui condolens interitu
Mortis perire saeculum,
Salvasti mundum languidum,
Donans reis remedium.

Vergente mundi vespere,
Uti sponsus de thalamo,
Egressus honestissima
Virginis matris clausula. Amen.

Hymn II
...
... Amen.

Eu quero que o arquivo tenha esta aparência:

\small{\uppercase{Hymn I}}\normalsize
\begin{verse}
Conditor alme siderum,\
Aeterna lux credentium,\
Christe, redemptor omnium,\
Exaudi preces supplicum.\!

Qui condolens interitu\
Mortis perire saeculum,\
Salvasti mundum languidum,\
Donans reis remedium.\!

Vergente mundi vespere,\
Uti sponsus de thalamo,\
Egressus honestissima\
Virginis matris clausula. Amen.\!
\end{verse}
\small{\uppercase{Hymn II}}\normalsize
\begin{verse}
...\
... Amen.\!
\end{verse}

Eu consegui descobrir muito disso. mas eu quero saber como usar sed com várias linhas corretamente para obter os parágrafos formatados.

Eu tentei coisas com sed '/Hymn/,/Amen/ { /Hymn\|Amen/ !{...' E H ou N , mas eu nunca consigo entender direito.

    
por ftherese 29.10.2015 / 18:13

2 respostas

2

Algo parecido com isto:

sed '/Hymn/,/Amen/{                                 # in this range
/Hymn/{                                             # if line matches Hymn
s/.*/\small\{\uppercase\{&\}\}\normalsize/       # replace as required
h                                                   # copy over the hold space
s/.*/\begin\{verse\}/                              # replace with \begin{verse}
H                                                   # append to hold space
d                                                   # delete the line
}
/Amen/!{                                            # if line doesn't match Amen 
/^$/!{                                              # and if line is not empty
s/$/\\/                                           # add trailing \
}
H                                                   # append to hold space
d                                                   # then delete line
}
//{                                                 # if line matches Amen
s/$/\\!/                                          # add trailing \!
H                                                   # append to hold space
s/.*/\end\{verse\}/                                # replace with \end{verse}
H                                                   # append to hold space
s/.*//                                              # empty pattern space
x                                                   # exchange buffers
s/\n\n/!&/g                                         # add ! at end of each para
}
}
' infile

ou, se você preferir um gnu sed two-liner:

sed '/Hymn/,/Amen/{/Hymn/{s/.*/\small\{\uppercase\{\&\}\}\normalsize/;h;s/.*/\begin\{verse\}/;H;d}
/Amen/!{/^$/!{s/$/\\/};H;d};//{s/$/\\!/;H;s/.*/\end\{verse\}/;H;s/.*//;x;s/\n\n/!&/g}}' infile

Envie com sua amostra:

\small{\uppercase{Hymn I}}\normalsize
\begin{verse}
Conditor alme siderum,\
Aeterna lux credentium,\
Christe, redemptor omnium,\
Exaudi preces supplicum.\!

Qui condolens interitu\
Mortis perire saeculum,\
Salvasti mundum languidum,\
Donans reis remedium.\!

Vergente mundi vespere,\
Uti sponsus de thalamo,\
Egressus honestissima\
Virginis matris clausula. Amen.\!
\end{verse}

\small{\uppercase{Hymn II}}\normalsize
\begin{verse}
...\
... Amen.\!
\end{verse}
    
por 30.10.2015 / 10:48
0

Eu usaria perl no modo de parágrafo.

#!/usr/bin/env perl
# Usage: thisprogram < inputfile > outputfile
use strict;
use warnings;
use feature qw(say);

$/ = "\n\n";    # paragraph mode

while (<>) {
  # nuke last \n of paragraph due to
  s/[\n]+\z//;
  # the need to replace the mid-verse newlines with \
  s/\n/\\\n/g;
  # and now actually undo that while working on the first line
  s/(Hymn \w+)[\]+/\small{\uppercase{$1}}\normalsize\n\begin{verse}/;
  # and at the newline-free end of the paragraph, tack on the \! bit
  s/\z/\\!/;
  # emit
  say;
  if (m/Amen\./) {
    say "\end{verse}\n";
  } else {
    print "\n";
  }
}
    
por 29.10.2015 / 19:03