sed: insira algo antes das linhas subseqüentes que começam o mesmo, mas não são as mesmas

4

Eu tenho um arquivo LaTeX com uma entrada de glossário por linha:

...
\newglossaryentry{ajahn}{name=Ajahn,description={\textit{(Thai)} From the Pali \textit{achariya}, a Buddhist monk's preceptor: 'teacher'; often used as a title of the senior monk or monks at monastery. In the West, the forest tradition uses it for all monks and nuns of more than ten years' seniority}}
\newglossaryentry{ajivaka}{name={\=Aj\={\i}vaka},description={Sect of contemplatives contemporary with the Buddha who held the view that beings have no volitional control over their actions and that the universe runs according to fate and destiny}}
...

Aqui, estamos preocupados apenas com a parte \newglossaryentry{label} de cada linha.

As linhas do arquivo foram classificadas com sort , portanto, os rótulos duplicados aparecem assim:

\newglossaryentry{anapanasati}{name=\=an\=ap\=anasati,description={'Awareness of inhalation and exhalation'; using the breath, as a mediation object},sort=anapanasati}
\newglossaryentry{anapanasati}{name={\=an\=ap\=anasati},description={Mindfulness of breathing. A meditation practice in which one maintains one's attention and mindfulness on the sensations of breathing. \textbf{[MORE]}}}

Como faço para sed este arquivo, para inserir uma linha antes de duplicar marcadores?

#!/bin/sh

cat glossary.tex | sed '
/\newglossaryentry[{][^}]*[}]/{
    N;
    s/^\(\newglossaryentry[{][^}]*[}]\)\(.*\)\n/% duplicate\n\n/;
}' > glossary.sed.tex

Eu fiz isso até o comando acima, mas ele tem uma falha: ele lê as linhas para o espaço de padrões em pares, e então ele só funciona quando a duplicata passa a ser o par que ela leu.

Estes não corresponderão por exemplo:

\newglossaryentry{abhinna}{name={abhi\~n\~n\=a},description={Intuitive powers that come from the practice of concentration: the ability to display psychic powers, clairvoyance, clairaudience, the ability to know the thoughts of others, recollection of past lifetimes, and the knowledge that does away with mental effluents (see \textit{asava}).}}
\newglossaryentry{acariya}{name={\=acariya},description={Teacher; mentor. See \textit{kalyanamitta.}}}
\newglossaryentry{acariya}{name=\=acariya,description={Teacher},see=Ajahn}
\newglossaryentry{adhitthana}{name={adhi\d{t}\d{t}h\=ana},description={Determination; resolution. One of the ten perfections \textit{(paramis).}}}

Porque primeiro ele lê as linhas com abhinna e acariya , então lê acariya e aditthana .

Eu acho que isso precisa de um pouco mais de sed de mágica com espaço de espera e impressão condicional de linhas, mas não consegui entender.

    
por Gambhiro 02.04.2011 / 17:55

1 resposta

2

Isso é bastante complicado para sed, mais um trabalho para awk ou perl. Aqui está um script que encontra duplicatas consecutivas (mas permite linhas não correspondentes entre elas):

perl -l -pe '
    if (/^ *\newglossaryentry[* ]*{([^{}]*)}/) {
        print "% duplicate" if $1 eq $prev;
        $prev = $1;
    }'

É bastante fácil detectar duplicatas, mesmo em entradas não classificadas.

perl -l -pe '
    if (/^ *\newglossaryentry[* ]*{([^{}]*)}/) {
        print "% duplicate" if $seen{$1};
        ++$seen{$1};
    }'

Você também pode restringir facilmente a linhas consecutivas:

perl -l -pe '
    if (/^ *\newglossaryentry[* ]*{([^{}]*)}/) {
        print "% duplicate" if $1 eq $prev;
        $prev = $1;
    } else {undef $prev}'
    
por 02.04.2011 / 18:19