удалите строки в файле CSV, более старом, чем 7 дней

ip route get $(gethostip -d $NEXTSMTPHOP) должен показать интерфейс, который будет использоваться для Вашего исходящего трафика. Привязка интерфейса будет только влиять на слушание адресного для входящего трафика.

Таким образом, необходимо установить маршрутизацию способом, что следующий ТРАНЗИТНЫЙ УЧАСТОК SMTP (надо надеяться, статический IP) выходит через желаемый интерфейс.

2
06.07.2013, 02:31
5 ответов

Вот использование метода tail, date -d ..., awk, и просто функциональность Bash.

tail -n+2 file.csv | {
  while read line ; do
    tmstmp=$(echo "$line" | awk '{print $8}');
    [ $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) )) -lt $(( 60*60*24*7 )) ] && echo "$line";
  done;
}

Как это работает?

Вышеупомянутые синтаксические анализы строки из файла, file.csv, и get's 8-й столбец (дата), и затем вычисляет дельту между числом секунд с эпохи на данный момент и проанализированной датой. Если они - менее затем ценность 7 дней секунд затем, строка добирается, распечатал.

Отладка

Можно вставить эту строку для отладки то, что продолжается. Поместите его сразу после tmpstmp=... строка:

echo "TMSTMP: $tmstmp" "TMDELTA: $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) ))" "TMWINDOW: $(( 60*60*24*7 ))"

Пример

Для простоты я поместил вышеупомянутое в сценарий и назвал его rprttime.bash:

#!/bin/bash

tail -n+2 file.csv | {
  while read line ; do
    tmstmp=$(echo "$line" | awk '{print $8}');
    echo "TMSTMP: $tmstmp" "TMDELTA: $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) ))" "TMWINDOW: $(( 60*60*24*7 ))"
    [ $(( $(date -d "now" +%s) - $(date -d "$tmstmp" +%s) )) -lt $(( 60*60*24*7 )) ] && echo "$line";
  done;
}

Теперь, когда мы выполняем его:

$ ./rprttime.bash
TMSTMP: 05/07/2013 TMDELTA: 5157421 TMWINDOW: 604800
TMSTMP: 08/05/2012 TMDELTA: 28917421 TMWINDOW: 604800
TMSTMP: 04/04/2013 TMDELTA: 8008621 TMWINDOW: 604800
TMSTMP: 04/03/2013 TMDELTA: 8095021 TMWINDOW: 604800
TMSTMP: 04/03/2013 TMDELTA: 8095021 TMWINDOW: 604800
TMSTMP: 3/22/2013 TMDELTA: 9131821 TMWINDOW: 604800
TMSTMP: 04/02/2013 TMDELTA: 8181421 TMWINDOW: 604800
TMSTMP: 11/15/2012 TMDELTA: 20101021 TMWINDOW: 604800
TMSTMP: 3/22/2013 TMDELTA: 9131821 TMWINDOW: 604800

При изменении окна времени с 7 дней, чтобы сказать 60 дней и отключить строку отладки, Вы будете видеть некоторые распечатанные строки:

$ date
Fri Jul  5 16:49:19 EDT 2013

$ ./rprttime.bash
T001028    1    1   1   0   0     0   05/07/2013
2
27.01.2020, 21:55

При вычислении даты, до которой строки должны быть проигнорированы перед вызовом awk затем, можно сделать это:

awk -v cmpdate=20130628 '{line=$0; dateval=$8;FS="/"; $0=dateval; 
  thisdate=$3*10000+$1*100+$2; if (thisdate>cmpdate) print line; FS=" ";}' file

Редактирование 1:

Сброс FS к его исходному значению в конце. Я протестировал свой код со всего одной строкой входа так, чтобы это не имело значения...

1
27.01.2020, 21:55
  • 1
    Это - некоторая рвота neckbeard тут же.Мило. –  Mel Boyce 05.07.2013, 15:52
  • 2
    @MelBoyce, что "neckbeard рвота"? Это не звучит очень дополнительным. –  terdon♦ 05.07.2013, 16:04
  • 3
    О, это очень дополнительно. Мы должны все стремиться к тому уровню вуду инструмента. –  Mel Boyce 05.07.2013, 19:33
  • 4
    @MelBoyce - то, что Ваш термин или Вы услышали, что он использовал положительным способом прежде? Взгляните на мой вопрос здесь. –  terdon♦ 05.07.2013, 21:17
  • 5
    @terdon - Принятый ответ на english.stackexchange.com является в значительной степени правильным. neckbeard (по крайней мере, в контексте, используемом моими коллегами), является более мудрым гуру UNIX старшего возраста (обычно кто-то, кто начал использовать UNIX назад в шестидесятых или семидесятых), и контекст для "рвоты" в этом случае относится к неудобочитаемости, но сжатый из ответа. –  Mel Boyce 11.07.2013, 06:46

Я сделал бы это с Perl (выполните это от терминала):

$ perl -lane 'BEGIN{$date=`date +%s`; chomp($date)}    
            if($.==1){print}                         
            else{
                 $F[$#F]=~s/-/\//g; 
                 $fdate=`date -d "$F[$#F]" +%s`;     
                 chomp($fdate);                      
            print if $date-$fdate<604800;     
          }' file.csv

Этот сценарий работает путем вычисления сегодняшней даты в секундах с эпохи, затем перевода даты каждой строки к тому же формату, вычитания его из сегодняшней даты и печати, только если этому меньше чем 7 дней (7*24*60*60=604800).

Примечания

  • Работы сценария с секундами, это может быть немного слишком точно для того, что Вы имели в виду. Сообщите мне если так, и я изменю его для работы на уровне дней вместо этого.

  • Я также преобразовываю MM-DD-YYYY кому: MM/DD/YYYYна лету это не может быть необходимо, если Ваш входной файл гомогенно отформатирован, но он необходим для примера, который Вы отправили.

0
27.01.2020, 21:55

Еще один ответ с ограниченными ветвлениями

Как существует много ветвлений к whipe, существует путь к тому, чтобы сделать это использование sed и только 1 ветвление к /bin/date:

sedstr=""
{
    i=1;
    read now;
    while read line;do
        ((i++));
        [ $(( (now-line) /86400 )) -gt 143 ] && sedstr="${i}d;$sedstr"
      done
}< <(
    sed -ne $'s/^.*[ \t,]//g;y|-|/|;/[0-9]$/p;1inow' < file.tsv |
        date -f - +%s
)
sed -e "$sedstr" < file.tsv
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp
T001028     1   1   1   0   0   0   05-07-2013
T001261     1   1   1   0   0   1   04-04-2013
T001345     1   1   1   0   0   0   04-03-2013
T078503     1   1   1   0   0   0   04-03-2013

Последнее sed команда могла использоваться с -i для оперативной модификации вместо вывода к консоли.

echo $sedstr 
10d;9d;8d;7d;3d;

sed -e $sedstr -i file.tsv 
cat file.tsv 
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp
T001028     1   1   1   0   0   0   05-07-2013
T001261     1   1   1   0   0   1   04-04-2013
T001345     1   1   1   0   0   0   04-03-2013
T078503     1   1   1   0   0   0   04-03-2013
2
27.01.2020, 21:55

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

Вопрос обозначает csv (кома разделила значение) и подарок tsv (сентябрь вкладки vals), таким образом, мой сценарий будет работать на любой вид вкладки, кома или пространство отделились, значения (просто ищут последнее поле).

Никакое ветвление, perl сделает дату, анализирующую себя:

#!/usr/bin/perl -w

use strict;
use Date::Parse;

my $day=7;
if ($ARGV[0] && $ARGV[0] > 0) { $day=$ARGV[0]; shift; };

while (<>) {
    my @fields=split(/[ \t,]/);
    print if /^Person/ || str2time($fields[$#fields]) > time()-$day*86400;
};

Вы могли выполнить это без аргумента как фильтр или с именем файла как аргумент:

./dropOlderThan.pl < file.tsv
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp

./dropOlderThan.pl file.tsv
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp

Если первым аргументом будет число, то они будут интерпретироваться как число дня для хранения в выводе:

./dropOlderThan.pl 144 file.tsv
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp
T001028     1   1   1   0   0   0   05-07-2013
T001261     1   1   1   0   0   1   04-04-2013
T001345     1   1   1   0   0   0   04-03-2013
T078503     1   1   1   0   0   0   04-03-2013

И наконец, если Вы хотите изменить файл на месте:

perl -i dropOlderThan.pl 144 file.tsv 
cat file.tsv 
Person ID   VIP CS  SS  LT  FTLT    PS  Modified Datestamp
T001028     1   1   1   0   0   0   05-07-2013
T001261     1   1   1   0   0   1   04-04-2013
T001345     1   1   1   0   0   0   04-03-2013
T078503     1   1   1   0   0   0   04-03-2013
1
27.01.2020, 21:55

Теги

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