Создание таблицы из списка с использованием ближайшего значения? - PullRequest
1 голос
/ 02 февраля 2020

У меня есть список, похожий на этот ...

1ID:42
2ID:85853
Name:Chris
Age:99
Species:Monkey
Name:Bob
Age:23
Species:Fish
Name:Alex
Age:67
Species:Cat
1ID:987
2ID:775437
Name:Tiffany
Age:32
Species:Dog
1ID:777
2ID:65336
Name:Becky
Age:122
Species:Hippo

Я хочу создать таблицу, в которой некоторые данные взяты из ближайшего результата. Это мешает мне просто заменить "\ n", "Name:" и т. Д. c на мой стол.

Это то, что я хочу закончить ...

Chris 99 Monkey 42 85853
Bob 23 Fish 42 85853
Alex 67 Cat 42 85853
Tiffany 32 Dog 987 775437
Becky 122 Hippo 777 65336

Надеюсь, это имеет смысл. Последние 2 столбца взяты из ближайших предыдущих 1ID и 2ID. После значений «ID» может быть любое количество записей.

Ответы [ 5 ]

3 голосов
/ 02 февраля 2020

Допущения:

  • данные всегда форматируются в том виде, как они представлены, и всегда есть полный 3-х кортеж из названия / возраста / вида
  • первое поле каждой строки пишется / пишется с большой буквы точно так же, как в примере (решение основано на точном совпадении)

Пример файла данных:

$ cat species.dat
1ID:42
2ID:85853
Name:Chris
Age:99
Species:Monkey
Name:Bob
Age:23
Species:Fish
Name:Alex
Age:67
Species:Cat
1ID:987
2ID:775437
Name:Tiffany
Age:32
Species:Dog
1ID:777
2ID:65336
Name:Becky
Age:122
Species:Hippo

One awk решение:

awk -F":" '
$1 == "1ID"     { id1=$2  ; next }
$1 == "2ID"     { id2=$2  ; next }
$1 == "Name"    { name=$2 ; next }
$1 == "Age"     { age=$2  ; next }
$1 == "Species" { print name,age,$2,id1,id2 }
' species.dat

ПРИМЕЧАНИЕ. Пункты next являются необязательными, поскольку каждая строка совпадает с указанным значением c в поле 1 ($1).

Запуск вышеуказанного создает:

Chris 99 Monkey 42 85853
Bob 23 Fish 42 85853
Alex 67 Cat 42 85853
Tiffany 32 Dog 987 775437
Becky 122 Hippo 777 65336
2 голосов
/ 03 февраля 2020

Вы бы попробовали следующее:

awk -F: '{a[$1]=$2} /^Species:/ {print a["Name"],a["Age"],a["Species"],a["1ID"],a["2ID"]}' file.txt
2 голосов
/ 03 февраля 2020

Пожалуйста, посмотрите, соответствует ли следующий код вашим требованиям

use strict;
use warnings;
use feature 'say';

my($id1,$id2,$name,$age,$species);
my $ready = 0;

$~ = 'STDOUT_HEADER';
write;
$~ = 'STDOUT';

while(<DATA>) {
    $id1     = $1 if /^1ID:\s*(\d+)/;
    $id2     = $1 if /^2ID:\s*(\d+)/;
    $name    = $1 if /^Name:\s*(\w+)/;
    $age     = $1 if /^Age:\s*(\d+)/;
    $species = $1 if /^Species:\s*(\w+)/;
    $ready   = 1  if /^Species:/;           # trigger flag for output
    if( $ready ) {
        $ready = 0;
        write;
    }
}

format STDOUT_HEADER =
Name     Age Species  Id1     Id2
---------------------------------
.

format STDOUT =
@<<<<<<< @>> @<<<<<<  @>> @>>>>>>
$name, $age, $species, $id1, $id2
.

__DATA__
1ID:42
2ID:85853
Name:Chris
Age:99
Species:Monkey
Name:Bob
Age:23
Species:Fish
Name:Alex
Age:67
Species:Cat
1ID:987
2ID:775437
Name:Tiffany
Age:32
Species:Dog
1ID:777
2ID:65336
Name:Becky
Age:122
Species:Hippo

Вывод

Name     Age Species  Id1     Id2
---------------------------------
Chris     99 Monkey    42   85853
Bob       23 Fish      42   85853
Alex      67 Cat       42   85853
Tiffany   32 Dog      987  775437
Becky    122 Hippo    777   65336
0 голосов
/ 03 февраля 2020

Это может сработать для вас (GNU sed):

sed -En '/^1ID./{N;h};/^Name/{N;N;G;s/\S+://g;s/\n/ /gp}' file

Уложить ID в ячейку удержания. Соберите запись в пространстве образца, добавьте ID, уберите метки и замените символы новой строки пробелами.

0 голосов
/ 02 февраля 2020

Вот пример в Perl:

use feature qw(say);
use strict;
use warnings;

my $fn = 'file.txt';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
my ($id1, $id2);
while( my $line = <$fh> ) {
    chomp $line;
    if ( $line =~ /^1ID:(\d+)/ ) {
        $id1 = $1;
    }
    elsif ( $line =~ /^2ID:(\d+)/ ) {
        $id2 = $1;
    }
    else {
        my ( $name, $age, $species ) = get_block( $fh, $line );
        say "$name $age $species $id1 $id2";
    }
}

close $fh;


sub get_value {
    my ( $line, $key ) = @_;

    my ($key2, $value) = $line =~ /^(\S+):(.*)/;
    if ( $key2 ne $key ) {
        die "Bad format";
    }
    return $value;
}

sub get_block {
    my ( $fh, $line ) = @_;

    my $name = get_value( $line, 'Name' );
    $line = <$fh>;
    my $age = get_value( $line, 'Age' );
    $line = <$fh>;
    my $species = get_value( $line, 'Species' );
    return ( $name, $age, $species );
}

Вывод :

Chris 99 Monkey 42 85853
Bob 23 Fish 42 85853
Alex 67 Cat 42 85853
Tiffany 32 Dog 987 775437
Becky 122 Hippo 777 65336
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...