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


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.