Alfabetik satırların metinlerini kabuktaki sayısal satırlarla nasıl birleştirebilirim?


10

Bunun gibi metin içeren bir dosya var:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

vb...

Ve Alfabetik çizgileri Sayısal çizgileri ile eşleştirmek istiyorum, böylece bunlar şöyle:

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

Bunu başarmanın basit bir yolunu bilen var mı?


Sen söz emacsBir arıyorsunuz .. elispçözelti, ya da nasıl emacs'dan içinden bir kabuk komut dosyasını çalıştırmak için?
Peter.O

Yanıtlar:


3

Kullanmanın tek yolu perl:

İçeriği 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 ];
}

İçeriği infile:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

Gibi çalıştırın:

perl script.pl infile

Ve sonuç:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890

İlginç ... Sizin iki regex ikame hatları Kaldır baştaki ve sondaki boşluklar daha hızlı backreferencing olmayan açgözlü kullanan tek bir satır daha 1.6 kere çalıştırın: s/\A\s*(.*?)\s*\Z/\1/.
Peter.O

4

Gelen awk, iyi biçimlendirilmiş dosyayı varsayarak boş satırları koruyarak ama mantık dosyasını kontrol eklenebilir:

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

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

veya tek bir adımda geçici dosyalar olmadan

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

Son sedadım, boş satırlardaki ayırıcıyı kaldırır, bu da paste...


3

Emacs ile metin satırlarını kesmek ve sayısal satırlardan önce yapıştırmak için dikdörtgen işlemleri kullanın.


Teşekkürler, ancak 15000+ satır için gerçekten uygun değil! + 1 bir çalışma fikri için ve temsilcisi gerekir :)
NWS

2

Girişler sıralıysa,

  1. Girişi aşağıdakileri kullanarak alfabetik girişlere ve sayısal girişlere ayırın grep:

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. Ortaya çıkan iki dosyaya katılın alphave şunu digitkullanın paste:

    • paste alpha digit( -d " "sekme yerine boşluk kullanması için ekleyebilirsiniz )

1
Geçici dosyaları olmadan: paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file)ya da tek bir işlem ikamesi ile: grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file).
jfg956

1

Çok kötü awk'nin güzel push / pop / unshift / shift işlevleri yok. İşte kısa bir Perl snippet'i

perl -M5.010 -lne '
  given ($_) {
    when (/^[[:alpha:]]+$/) {push @alpha, $_}
    when (/^\d+$/) {say shift(@alpha), " ", $_}
    default {say}
  }
'

Çalıştırdığımda, grup başına ekstra (önde gelen) bir boş satır çıkarıyor.
Peter.O

defaultMadde nedeniyle , boş satırlar hemen yazdırılır, bu nedenle "1234" den önceki boşluk "AAAA" satırından önce gösterilir.
glenn jackman

0

Metin içeren bir dosya verin, praşağıdaki gibi ikame sözdizimini kullanmayı deneyin ve işleyin:

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

Genişliği ayarlayabilir -w9veya boşlukları kaldırabilirsiniz sed "s/ //g".

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.