В ударе или ksh, помещенном имена файлов в массив, и, выполняют итерации по тому массиву в обратном порядке.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
Код выше также работает в zsh если ksh_arrays
опция установлена (это находится в ksh режиме эмуляции). В zsh существует более простой метод, который должен инвертировать порядок соответствий через спецификатор шарика:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX не включает массивы, поэтому если Вы хотите быть портативными, Ваша единственная опция непосредственно сохранить массив строк является позиционными параметрами.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
Чтобы сделать это Ваш путь, который должен был бы быть чем-то как:
POSIXLY_CORRECT=1 awk '
{
n = ""; r = $0
while (match(r, /[[:alpha:]]{3} [[:alpha:]]{3} +[0-9]+ ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/)) {
c = "date -d\"" substr(r,RSTART,RLENGTH) "\" +%s"
c | getline b
close(c)
n = n substr(r,1,RSTART-1) b
r = substr(r,RSTART+RLENGTH)
}
print n r
}'
Вот альтернативный подход (использование mktime
):
#!/bin/awk -f
{
split($6,A,":");
S1=sprintf("%d %d %d %d %d %d",$7,$4,$5,A[1],A[2],A[3])
T1=mktime(S1)
if ($8=="-") {
split($12,A,":");
S2=sprintf("%d %d %d %d %d %d",$13,$10,$11,A[1],A[2],A[3])
T2=mktime(S2)
print $1,$2,T1,$8,T2,$14
}
else {
print $1,$2,T1,$8,$9,$10
}
}
Вы могли сделать это как это с GNU sed:
convert_date.sed
: a
s/(([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4})(.*)/\n\4\n\1/
h
s/.*\n//
s/^/date -d "/
s/$/" +%s/e
G
s/([^\n]+)\n([^\n]+)\n([^\n]+)\n.*/\2\1\3/
/([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/ta
Выполните его как это:
sed -rf convert_date.sed infile
Вывод:
pablo tty8 1351770681 still logged in
(unknown tty8 1351770657 - 1351770681 (00:00)
pablo tty2 1351770639 still logged in
pablo tty7 1351770585 - 1351770656 (00:01)
(unknown tty7 1351769672 - 1351770585 (00:15)
Это может выглядеть немного пугающим сначала, но идея не сложный. Это регулярное выражение, ([A-Za-z]{3} ){2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2} [0-9]{4}
, то, которое происходит в первой замене и условном выражении в конце, соответствует типу даты, используемому во входе, это получает и изолирует дату. Окружающие биты хранятся в пространстве хранения в то время как date -d
выполняется в полученную дату. Наконец, все биты собраны в пространстве шаблона и реорганизованы в правильный порядок.
Условное выражение в конце повторяет процесс, если какие-либо даты остаются в пространстве шаблона.
С perl
и Date::Manip
модуль:
perl -MDate::Manip -pe '
s/\w{3} \w{3} +\d+ \d\d:\d\d:\d\d \d+/
UnixDate ParseDate("$&"),"%s"/ge'
Решение для Perl, предоставленное Stephane, требует неосновного модуля Perl. Можно было использовать базовый модуль (начиная с 5.10), Время:: Часть, так же:
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
my $t = Time::Piece->new;
while (<>) {
s{\w{3}\s(\w{3}\s\d{1,2}\s\d\d:\d\d:\d\d\s\d{4})}
{$t=Time::Piece->strptime($1,"%b %d %H:%M:%S %Y");
sprintf "%s",$t->epoch}ge;
print;
}