Bagaimana cara menggabungkan teks garis alfabet dengan garis numerik di shell?

10

Saya Memiliki file yang memiliki teks seperti ini:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

dll ...

Dan saya ingin mencocokkan garis Alfabet dengan garis Numerik sehingga menjadi seperti ini:

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

Adakah yang tahu cara sederhana untuk mencapainya?

NWS
sumber
Anda menyebutkan emacs.. Apakah Anda mencari elispsolusi, atau bagaimana menjalankan shell-script dari dalam emacs?
Peter.O
Dalam Vim: Gabungkan banyak baris (dua blok) di SO
kenorb

Jawaban:

3

Salah satu cara menggunakan perl:

Isi dari 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 ];
}

Isi dari infile:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

Jalankan seperti:

perl script.pl infile

Dan hasil:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890
Birei
sumber
Menarik ... Anda dua baris substitusi regex yang Remove ruang terkemuka dan trailing berjalan sekitar 1,6 kali lebih cepat dari satu baris yang menggunakan backreferencing dan non-serakah: s/\A\s*(.*?)\s*\Z/\1/.
Peter.O
4

Dalam awk, mempertahankan baris kosong, dengan asumsi file diformat dengan baik, tetapi logika dapat ditambahkan untuk memeriksa file:

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
sumber
4
<input sed -nr '/^[A-Z]{4}$/,/^$/w out1
                /^[0-9]{4}$/,/^$/w out2'
paste -d' ' out1 out2 |sed 's/^ $//' 

atau, dalam satu langkah, tanpa file temp

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

Langkah terakhir sedmenghilangkan pembatas pada baris kosong, yang diperkenalkan oleh paste...

Peter.O
sumber
3

Dengan emacs gunakan operasi persegi panjang untuk memotong garis teks dan menempelkannya sebelum garis numerik.

tom
sumber
Terima kasih, tetapi tidak cocok untuk 15000+ baris! +1 untuk ide yang berfungsi dan Anda perlu perwakilan :)
NWS
2

Jika entri dalam urutan,

  1. Membagi input menjadi entri alfabet dan entri numerik, menggunakan grep:

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. Gabung dua file yang dihasilkan, alphadan digit, menggunakan paste:

    • paste alpha digit(Anda dapat menambahkan -d " "sehingga menggunakan spasi alih-alih tab)
njsg
sumber
1
Tanpa file temp: paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file)atau dengan proses substitusi tunggal: grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file).
jfg956
1

Sayang sekali, awk tidak memiliki fungsi push / pop / unshift / shift yang bagus. Berikut cuplikan singkat Perl

perl -M5.010 -lne '
  given ($_) {
    when (/^[[:alpha:]]+$/) {push @alpha, $_}
    when (/^\d+$/) {say shift(@alpha), " ", $_}
    default {say}
  }
'
glenn jackman
sumber
Ketika saya menjalankannya, itu menghasilkan garis kosong (memimpin) tambahan per grup.
Peter.O
Karena defaultklausa tersebut, garis-garis kosong segera dicetak, sehingga kosong sebelum "1234" akan ditampilkan sebelum garis "AAAA".
glenn jackman
0

Berikan file dengan teks, coba gunakan prdan proses sintaksis substitusi seperti di bawah ini:

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

Anda dapat menyesuaikan lebar dengan -w9atau menghapus spasi dengan sed "s/ //g".

kenorb
sumber