Como juntar múltiplas linhas baseadas em um padrão?

4

Eu quero unir várias linhas em um arquivo com base em um padrão que as duas linhas compartilham.

Este é o meu exemplo:

{101}{}{Apples}
{102}{}{Eggs}
{103}{}{Beans}
{104}...
...

{1101}{}{This is a fruit.}
{1102}{}{These things are oval.}
{1103}{}{You have to roast them.}
{1104}...
...

Quero juntar as linhas {101}{}{Apples} e {1101}{}{This is a fruit.}

para uma linha {101}{}{Apples}{1101}{}{This is a fruit.} para processamento adicional.

O mesmo vale para as outras linhas.

Como você pode ver, ambas as linhas compartilham o número 101, mas não tenho idéia de como fazer isso. Alguma idéia?

/ EDIT:

Eu encontrei uma "solução alternativa":

Primeiro, exclua todos os caracteres "{1" anteriores do grupo dois no modo VISUAL BLOCK com C-V (ou atalho semelhante), depois classifique todas as linhas por número com :%sort n e junte todas as segundas linhas com :let @q = "Jj" seguido por 500@q .

Isso funciona, mas me deixa com {101}{}{Apples} 101}{}{This is a fruit.} . Eu precisaria adicionar os caracteres ausentes "{1" em cada linha, não exatamente o que eu quero. Qualquer ajuda apreciada.

    
por ryz 30.01.2011 / 22:11

3 respostas

3

Em vez de excluir o {1 , faça

:%sort rn /\d\d\d}/

Isso fará uma ordenação numérica, mas em cada linha só verá três dígitos seguidos de um}.

Além disso, para participar das linhas depois, eu faria

:g/{\d\d\d}/j!
    
por 31.01.2011 / 01:42
2

Aqui está uma maneira de fazer isso no shell com um arquivo:

join -j 2 \
    <(sed -n '/^{...}/{s/{/{ /;s/}/ }/;p}' inputfile) \
    <(sed -n '/^{....}/{s/{./& /;s/}/ }/;p}' inputfile) |
    sed 's/^\([^ ]*\) { }{}\({[^}]*}\) {1 }\({.*}\)$/{}{}{1}/'

Ele usa as duas primeiras invocações de sed para dividir o arquivo com base no número de dígitos entre o primeiro conjunto de chaves e adiciona espaços ao redor dos três últimos dígitos ( {101} se torna { 101 } e {1101} torna-se {1 101 } ). Em seguida, ele usa esses números de três dígitos como um campo para a chave de comando join ativada. O último comando sed coloca os dígitos de volta onde eles pertencem e remove os espaços extras adicionados anteriormente.

Um vim guru provavelmente poderia fazer algo melhor em vim . Eu poderia fazer algo mais simples do que o anterior usando o AWK.

    
por 30.01.2011 / 23:19
0

Aqui está um exemplo usando o editor Vim / Ex na linha de comando para um padrão:

$ ex +'redir @a|sil g/101}/' +'redi>>/dev/stdout|echon join(split(@a),"")' -scq! input.txt 
{101}{}{Apples}{1101}{}{This is a fruit.}

Para vários padrões, repita com comandos extras, adicione um loop ou faça um loop de shell, por exemplo,

$ for i in 'seq 1 3'; do ex +"redir @a|sil g/10$i}/" +'redi>>/dev/stdout|echo join(split(@a),"")' -scq! input.txt; done
{101}{}{Apples}{1101}{}{Thisisafruit.}
{102}{}{Eggs}{1102}{}{Thesethingsareoval.}
{103}{}{Beans}{1103}{}{Youhavetoroastthem.}

Usando apenas shell para analisar os dados, é muito mais simples, por exemplo:

$ grep "101}" input.txt | xargs
{101}{}{Apples} {1101}{}{This is a fruit.}

Para várias linhas:

$ for i in 'seq 1 4'; do grep "10$i}" input.txt | xargs; done
{101}{}{Apples} {1101}{}{This is a fruit.}
{102}{}{Eggs} {1102}{}{These things are oval.}
{103}{}{Beans} {1103}{}{You have to roast them.}
    
por 15.09.2017 / 22:40

Tags