Como mesclar texto de linhas alfabéticas com as linhas numéricas no shell?

10

Eu tenho um arquivo que possui texto como este:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

etc ...

E eu quero combinar as linhas alfabéticas com as linhas numéricas para que elas sejam assim:

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

Alguém sabe de uma maneira simples de conseguir isso?

NWS
fonte
Você mencionou emacs.. Você está procurando uma elispsolução ou como executar um shell-script no emacs?
Peter.O

Respostas:

3

Uma maneira de usar perl:

Conteúdo de script.pl:

use warnings;
use strict;

## Check arguments.
die qq[Usage: perl $0 <input-file>\n] unless @ARGV == 1;

my (@alpha, @digit);

while ( <> ) {
        ## Omit blank lines.
        next if m/\A\s*\Z/;

        ## Remove leading and trailing spaces.
        s/\A\s*//;
        s/\s*\Z//;

        ## Save alphanumeric fields and fields with
        ## only digits to different arrays.
        if ( m/\A[[:alpha:]]+\Z/ ) {
                push @alpha, $_;
        }
        elsif ( m/\A[[:digit:]]+\Z/ ) {
                push @digit, $_;
        }
}

## Get same positions from both arrays and print them
## in the same line.
for my $i ( 0 .. $#alpha ) {
        printf qq[%s %s\n], $alpha[ $i ], $digit[ $i ];
}

Conteúdo de infile:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

Execute-o como:

perl script.pl infile

E resultado:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890
Birei
fonte
Interessante ... Suas duas linhas de substituição de regex que Remova esquerda e à direita espaços correr cerca de 1,6 vezes mais rápido do que uma única linha que utiliza referência anterior e não-ganancioso: s/\A\s*(.*?)\s*\Z/\1/.
Peter.O
4

Em awk, preservando linhas vazias, assumindo que o arquivo esteja bem formatado, mas a lógica pode ser adicionada para verificar o arquivo:

awk -v RS="" '{for(i=1; i<=NF; i++) a[i]=$i
  getline
  for(i=1; i<=NF; i++) print a[i] " " $i
  print ""}' file
jfg956
fonte
4
<input sed -nr '/^[A-Z]{4}$/,/^$/w out1
                /^[0-9]{4}$/,/^$/w out2'
paste -d' ' out1 out2 |sed 's/^ $//' 

ou, em uma única etapa, sem arquivos temporários

paste -d' ' <(sed -nr '/^[A-Z]{4}$/,/^$/p' input) \
            <(sed -nr '/^[0-9]{4}$/,/^$/p' input) | sed 's/^ $//' 

A última sedetapa remove o delimitador sobre as linhas em branco, que é introduzido por paste...

Peter.O
fonte
3

Com o emacs, use operações retangulares para cortar as linhas de texto e colá-las antes das linhas numéricas.

tom
fonte
Obrigado, mas não é realmente adequado para mais de 15000 linhas! + 1 para uma idéia de trabalho e você precisa o representante :)
NWS
2

Se as entradas estiverem em ordem,

  1. Divida a entrada em entradas alfabéticas e numéricas, usando grep:

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. Junte os dois arquivos resultantes alphae digit, usando paste:

    • paste alpha digit(você pode adicionar -d " "para usar um espaço em vez de uma guia)
njsg
fonte
1
Sem arquivos temporários: paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file)ou com uma única substituição de processo: grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file).
Jfg956
1

O awk muito ruim não possui boas funções push / pop / unshift / shift. Aqui está um pequeno fragmento de Perl

perl -M5.010 -lne '
  given ($_) {
    when (/^[[:alpha:]]+$/) {push @alpha, $_}
    when (/^\d+$/) {say shift(@alpha), " ", $_}
    default {say}
  }
'
Glenn Jackman
fonte
Quando eu o executo, ele gera uma linha em branco extra (principal) por grupo.
Peter.O
Devido à defaultcláusula, as linhas em branco são impressas imediatamente; portanto, o espaço em branco antes de "1234" será exibido antes da linha "AAAA".
Glenn Jackman
0

Forneça um arquivo com texto, tente usar pre processe a sintaxe de substituições, conforme abaixo:

$ pr -mt <(grep -i "^[a-z]" file.txt) <(grep -i "^[0-9]" file.txt)
AAAA                    1234
BBBB                    5678
CCCC                    9012
DDDD                    3456
EEEE                    7890

Você pode ajustar a largura -w9ou remover espaços por sed "s/ //g".

kenorb
fonte