我正在使用sed
重新格式化许多纯文本文件以使用 LaTeX 进行编译。该文件包含各个部分,其中包含提供范围的关键字。我正在处理的部分之一是赞美诗。赞美诗以关键字开头Hymn
,以单词结束。Amen.
赞美诗的文本应根据“诗句”上下文进行格式化。
这是一个示例输入文件:
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.
我希望文件看起来像这样:
\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}
我已经能够弄清楚其中的大部分内容。但我想知道如何sed
正确使用多行来格式化段落。
sed '/Hymn/,/Amen/ { /Hymn\|Amen/ !{...'
我已经尝试过And H
or 的方法N
,但我似乎永远无法完全正确。
答案1
像这样的东西:
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
或者,如果您更喜欢gnu sed
两行:
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
示例输出:
\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}
答案2
我会perl
在段落模式下使用。
#!/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";
}
}