Як об’єднати текст алфавітних рядків з числовими рядками в оболонці?


10

У мене є файл із таким текстом:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

тощо ...

І я хочу співставити алфавітні лінії з числовими лініями, щоб вони були такими:

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

Хтось знає простий спосіб досягти цього?


Ви згадуєте emacs.. Ви шукаєте elispрішення або як запустити скрипт оболонки зсередини emacs?
Пітер.О

Відповіді:


3

Один із способів використання perl:

Вміст 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 ];
}

Вміст infile:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

Виконайте це так:

perl script.pl infile

І результат:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890

Цікаві ... Два ваших регулярних виразів лінії заміщення , які видалити початкові і кінцеві пробіли бігають в 1,6 рази швидше , ніж в одному рядку , яка використовує посилальної і не жадібний: s/\A\s*(.*?)\s*\Z/\1/.
Пітер.О

4

В awk, зберігаючи порожні рядки, якщо припустити , що файл добре відформатований, але логіка може бути додано , щоб перевірити файл:

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/^ $//' 

або, в один крок, без тимчасових файлів

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

Останній sedкрок видаляє роздільник на порожні рядки, який вводиться paste...


3

Використовуйте операції прямокутника, щоб вирізати рядки тексту та вставити їх перед числовими рядками.


Дякую, але не дуже підходить для 15000+ ліній! + 1 для робочої ідеї і вам потрібен представник :)
NWS

2

Якщо записи в порядку,

  1. Розбийте вхід на алфавітні та числові записи, використовуючи grep:

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. З’єднайте два отримані файли alphaта digit, використовуючи paste:

    • paste alpha digit(ви можете додати, -d " "щоб він використовував пробіл замість вкладки)

1
Без тимчасових файлів: paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file)або за допомогою одного процесу заміщення: grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file).
jfg956

1

Дуже погано awk не має приємних функцій push / pop / unhift / shift. Ось короткий фрагмент Perl

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

Коли я запускаю його, він видає додатковий (провідний) порожній рядок на групу.
Пітер.О

Зважаючи на defaultпункт, порожні рядки негайно друкуються, тому порожнє перед "1234" відображатиметься перед рядком "AAAA".
glenn jackman

0

Надайте файл із текстом, спробуйте використовувати prта обробити синтаксис підстановок, як показано нижче:

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

Ви можете налаштувати ширину на -w9або видалити пробіли sed "s/ //g".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.