Преобразование некоторых плохо разделенных данных в полезный CSV.

Отвечать на отдельные вопросы в режиме реального времени, но имейте в виду, что Stack Exchange работает лучше всего, когда вы задаете только один вопрос на вопрос.

Затем я снова запустил службу exim, я отправил еще одно письмо, ожидая, что получу его на своем vps, как и раньше, но нет, я получил его в Outlook, даже когда мой vps имеет более высокий приоритет, например если vps-отправитель внесет его в «черный список», так как он потерпел неудачу из-за того, что я остановил службу exim, он даже не пытался отправить его (согласно / var / log / exim / mainlog), nslookup напрямую вернул запись MX outlook.

Итак ...Служба exim в vps отправителя занесла в черный список эту запись mx или что-то в этом роде? В таком случае, как я могу отменить это?

Клиент SMTP, возможно, кэширует (но не заносит в постоянный черный список) тот факт, что MX, который он ранее пытался использовать, недоступен. Клиенты SMTP могут делать это бесплатно. С точки зрения клиента, он может считать ответственность за доставку почты, которая будет передана, если любой один из MX для целевого домена его принял.

Целевой домен выразил предпочтение , для которого MX в идеале должен получать сообщения с использованием приоритетов MX, но клиенты не гарантируют, что это соблюдают. Как оператор домена вы должны предпринять шаги, чтобы убедиться, что почта в конечном итоге доставляется правильно, независимо от того, какой из ваших серверов MX принимает ее. Это может быть сделано с промежуточным хранением или с настройкой всех MX-серверов с возможностью доступа к одной и той же общей почтовой буфере или к чему угодно, на самом деле.

Есть ли способ получать почту на 2 серверах?

Нет. Клиент SMTP отвечает за доставку почты на один MX. Если вам нужно, чтобы почта доставлялась в несколько мест, ваши MX должны разбивать ее на несколько копий при получении и доставлять каждую копию на следующий переход.

Что произойдет, если я установлю две или более записей MX с одинаковым приоритетом?

Ожидается, что клиенты SMTP будут рассматривать записи MX как имеющие одинаковый приоритет. Они могут выполнять циклический переход между ними, балансировать нагрузку между ними или просто выбирать одно из них случайным образом из списка.Результат более или менее такой же, как если бы у вас был один MX, но этот MX имеет несколько записей A и / или AAAA .

13
02.03.2017, 00:18
7 ответов

Вы можете использовать Perl для циклического перебора CSV-файла и накопления суммы соответствующих типов в хеш-коде в процессе. И, в конце концов, отобразите информацию, собранную для каждого идентификатора.

Структура данных

%h = (
   ID1    =>  [ sum_of_type1, sum_of_type2, sum_of_type3 ],
   ...
)

Это помогает разобраться в приведенном ниже коде:

Perl

perl -wMstrict -Mvars='*h' -F'\s+|\|' -lane '
   $, = chr 44, next if $. == 1;

   my($count, $id, $type) = grep /./, @F;
   $h{ $id }[ $type-1 ] += $count}{
   print $_, map { $_ || 0 } @{ $h{$_} } for sort { $a <=> $b } keys %h
' yourcsvfile

Вывод

2,0,0,17892
3,0,0,6
4,15,253,19871
5,0,0,1000
...
3
27.01.2020, 19:52

Вы можете использовать этот код для суммирования значений на основе вашего столбца id,

Я добавил один оператор awk после вашего кода

awk 'BEGIN{OFS=",";} {split($line, part, " "); print part[1],part[2],part[4]}' abcd | awk '{ gsub (" ", "", $0); print}' | awk 'BEGIN{FS=OFS=SUBSEP=","}{arr[$2,$3]+=$1;}END{for ( i in arr ) print i,arr[i];}'

Продолжайте с этим ...

0
27.01.2020, 19:52

Perl приходит на помощь:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

<>;  # Skip the header.

my %sum;
my %types;
while (<>) {
    my ($count, $id, $type) = grep length, split '[\s|]+';
    $sum{$id}{$type} += $count;
    $types{$type} = 1;
}

say join ',', 'id', sort keys %types;
for my $id (sort { $a <=> $b } keys %sum) {
    say join ',', $id, map $_ // q(), @{ $sum{$id} }{ sort keys %types };
}

Он содержит две таблицы, таблицу типов и таблицу идентификаторов. Для каждого идентификатора хранится сумма по типу.

11
27.01.2020, 19:52

Если GNU datamash - вариант для вас, то

awk 'NR>1 {print $1, $2, $4}' OFS=, file | datamash -t, -s --filler=0 crosstab 2,3 sum 1
,1,2,3
10,0,0,588
12,0,0,10
14,0,0,883
17,0,0,98
18,17,0,77598
2,0,0,17892
21,0,0,10000
23,0,0,20000
27,0,0,63
3,0,0,6
35,0,0,2446
4,15,253,19871
5,0,0,1000
5
27.01.2020, 19:52

Один из способов сделать это - поместить все в хэш.

# put values into a hash based on the id and tag
awk 'NR>1{n[$2","$4]+=$1}
END{
    # merge the same ids on the one line
    for(i in n){
        id=i;
        sub(/,.*/,"",id);
        a[id]=a[id]","n[i];
    }
    # print everyhing
    for(i in a){
        print i""a[i];
    }
}'

изменить: мой первый ответ не дал правильного ответа на вопрос

12
27.01.2020, 19:52

мой взгляд, не слишком отличается от других. Использует GNU awk, который имеет массивы массивов

gawk '
    NR == 1 {next}
    {count[$2][$4] += $1}
    END {
        for (id in count) {
            printf "%d", id
            for (type=1; type<=3; type++) {
                # add zero to coerce possible empty string into a number 
                printf ",%d", 0 + count[id][type]
            }
            print ""        # adds the newline for this line
        }
    }
' file

, выходы

2,0,0,17892
3,0,0,6
4,15,253,19871
5,0,0,1000
10,0,0,588
12,0,0,10
14,0,0,883
17,0,0,98
18,17,0,77598
21,0,0,10000
23,0,0,20000
27,0,0,63
35,0,0,2446
1
27.01.2020, 19:52

Python (и библиотека pandas в частности) очень подходит для такой работы

data = """count  id     type
588    10 |    3
 10    12 |    3
883    14 |    3
 98    17 |    3
 17    18 |    1
77598    18 |    3
10000    21 |    3
17892     2 |    3
20000    23 |    3
 63    27 |    3
  6     3 |    3
 2446    35 |    3
 14    4 |    3
 15     4 |    1
253     4 |    2
19857     4 |    3
 1000     5 |    3"""

import pandas as pd
from io import StringIO # to read from string, not needed to read from file

df = pd.read_csv(StringIO(data), sep=sep='\s+\|?\s*', index_col=None, engine='python')

Это считывает данные csv в pandas DataFrame

    count  id  type
0     588  10     3
1      10  12     3
2     883  14     3
3      98  17     3
4      17  18     1
5   77598  18     3
6   10000  21     3
7   17892   2     3
8   20000  23     3
9      63  27     3
10      6   3     3
11   2446  35     3
12     14   4     3
13     15   4     1
14    253   4     2
15  19857   4     3
16   1000   5     3

Затем мы группируем эти данные по id, и возьмем сумму столбцов count

df_sum = df.groupby(('type', 'id'))['count'].sum().unstack('type').fillna(0)

С помощью unstack переформируем эти данные, чтобы переместить идентификаторы в столбцы, и fillna заполняет пустые поля 0

df_sum.to_csv()

Это возвращает

id,1,2,3
2,0.0,0.0,17892.0
3,0.0,0.0,6.0
4,15.0,253.0,19871.0
5,0.0,0.0,1000.0
10,0.0,0.0,588.0
12,0.0,0.0,10.0
14,0.0,0.0,883.0
17,0.0,0.0,98.0
18,17.0,0.0,77598.0
21,0.0,0.0,10000.0
23,0.0,0.0,20000.0
27,0.0,0.0,63.0
35,0.0,0.0,2446.0

Поскольку датафрейм содержит недостающие данные (пустые комбинации id-типов), pandas преобразует ints в float (ограничение внутренней работы). Если вы знаете, что входные данные будут только int, вы можете изменить предпоследнюю строку на df_sum = df.groupby(('type', 'id'))['count'].sum().unstack('type').fillna(0).astype(int)

4
27.01.2020, 19:52

Теги

Похожие вопросы