2014-02-10 5 views
0

У меня есть эта команда, которую я нашел here:Форматирование время эпохи

/usr/bin/truss /usr/bin/date 2>&1 | 
    nawk -F= '/^time\(\)/ {gsub(/" "/,"",$2);printf "0t%d=Y\n", $2-30*86400}' | 
    adb 

2014 Jan 11 09:48:54 который печатает. Кто-нибудь знает, как переформатировать выход в YYYYMMDDHH?

Мне нужно использовать ksh на Solaris. Я не могу использовать perl.

+0

я должен связать это на meta.stackoverflow.com «XY вопрос» ... почему вы не можете просто позвонить 'дата +"% Y% м% d% H "' (который непосредственно дает выход 'YYYYMMDDHH', см. http://pubs.opengroup.org/onlinepubs/009604599/utilities/date.html для возможностей спецификации формата)? –

ответ

0

Пара комментариев:

  • первая команда:

    /usr/bin/truss /usr/bin/date 2>&1 | 
    nawk -F= '/^time\(\)/ {gsub(/" "/,"",$2);printf "0t%d=Y\n", $2-30*86400}' 
    

может быть заменен на более легкий и простой

nawk 'BEGIN {printf("0t%d=Y\n",srand()-30*86400)}'` 
  • Я не уверен adb понимает синтаксис 0txx=Y, но mdb определенно делает.

Тем не менее, здесь есть то, что должно соответствовать вашим потребностям:

nawk 'BEGIN {printf("0t%d=Y\n",srand()-30*86400)}' | mdb | nawk ' 
function m2m(m) 
{ 
    if(m=="Jan")return 1 
    if(m=="Feb")return 2 
    if(m=="Mar")return 3 
    if(m=="Apr")return 4 
    if(m=="May")return 5 
    if(m=="Jun")return 6 
    if(m=="Jul")return 7 
    if(m=="Aug")return 8 
    if(m=="Sep")return 9 
    if(m=="Oct")return 10 
    if(m=="Nov")return 11 
    if(m=="Dec")return 12 
} 
{ 
    y=$1 
    m=$2 
    d=$3 
    split($4,t,":") 
    h=t[1] 
    min=t[2] 
    printf("%s%02d%02d%02d%02d\n",y,m2m(m),d,h,min) 
}' 

Примечания:

  • srand (не следует путать с rand) возвращает предыдущее семя при вызове.
  • Когда аргумент не передан, srand использует «время дня» в качестве семени.
  • Как srand инициализируется внутри под Solaris nawk, первый вызов вызывает время дня, то есть количество секунд, прошедших с эпохи.
  • Если вам нужен строго переносимый способ, вам нужно запустить первый вызов srand(), прежде чем получить его возвращаемое значение, но это не требуется в Solaris.
  • Это портативный (то есть POSIX), в отличие от truss.
+0

srand - генератор случайных чисел. Я не понимаю, как это получило мне дату 30 дней назад. – taylordurden

+0

Вы вводите в заблуждение 'rand' и' srand'. См. Мой обновленный ответ. – jlliagre

0

EDIT: Первоначально я сформировал ответ, который работает хорошо на Linux, но не на Solaris. Это намного дольше, с первоначальным ответом ниже.

Для этого просто в оболочке, на Solaris, можно использовать только функцию date. Вид. Вам нужно будет также создать некоторые функции оболочки, чтобы помочь с вычитанием дней с определенной даты.

Используя функцию ниже, вы можете сделать следующее, чтобы получить желаемые результаты:

$ mydate="$(date '+%Y%m%d')" 
$ hours="$(date '+%H')" 
$ echo "$(date_subtract "${mydate}" 30)${hours}" | adb 

или что-то подобное ...

В Solaris, команда date только обеспечивает григорианские даты.С этим труднее работать с целью этого вопроса, поэтому я создал функцию оболочки gregorian_to_julian, которая может конвертировать дату в формате «YYYYMMDD» в юлианскую дату «YYYYDDD».

function gregorian_to_julian { 
    # "Expecting input as YYYYMMDD." 
    typeset gregorian_date=$1 
    typeset _year=$(echo "${gregorian_date}" | cut -c1-4) 
    typeset _month=$(echo "${gregorian_date}" | cut -c5-6) 
    typeset _day=$(echo "${gregorian_date}" | cut -c7-8) 

    typeset days 
    days[01]=31 
    days[02]=$((days[01] + 28)) 
    if ((_year % 4 == 0)) && ((_year % 100 != 0)) || ((_year % 400 == 0)); then 
     days[02]=$((days[01] + 29)) 
    fi 
    days[03]=$((31 + days[02])) 
    days[04]=$((30 + days[03])) 
    days[05]=$((31 + days[04])) 
    days[06]=$((30 + days[05])) 
    days[07]=$((31 + days[06])) 
    days[08]=$((31 + days[07])) 
    days[09]=$((30 + days[08])) 
    days[10]=$((31 + days[09])) 
    days[11]=$((30 + days[10])) 

    typeset julian_date=0 
    case "${_month}" in 
     "01") julian_date=$_day ;; 
     "02") julian_date=$((days[01] + _day)) ;; 
     "03") julian_date=$((days[02] + _day)) ;; 
     "04") julian_date=$((days[03] + _day)) ;; 
     "05") julian_date=$((days[04] + _day)) ;; 
     "06") julian_date=$((days[05] + _day)) ;; 
     "07") julian_date=$((days[06] + _day)) ;; 
     "08") julian_date=$((days[07] + _day)) ;; 
     "09") julian_date=$((days[08] + _day)) ;; 
     "10") julian_date=$((days[09] + _day)) ;; 
     "11") julian_date=$((days[10] + _day)) ;; 
     "12") julian_date=$((days[11] + _day)) ;; 
    esac 
    julian_date="${_year}${julian_date}" 
    echo "${julian_date}" 
} 

Понимание того, что ОП хочет дату отформатированный как григорианский дату, я создал вторую функцию, которая преобразует julian_to_gregorian дату юлианского обратно.

function julian_to_gregorian { 
    # "Expecting input as YYYYDDD." 
    #set -x 
    typeset julian_date=$1 

    typeset _year="$(echo "${julian_date}" | cut -c1-4)" 
    typeset _month="" 
    typeset julian_day="$(echo "${julian_date}" | cut -c5-7)" 
    typeset -RZ2 _day=0 
    typeset days 
    days[01]=31 
    days[02]=$((days[01] + 28)) 
    if ((_year % 4 == 0)) && ((_year % 100 != 0)) || ((_year % 400 == 0)); then 
     days[02]=$((days[01] + 29)) 
    fi 
    days[03]=$((31 + days[02])) 
    days[04]=$((30 + days[03])) 
    days[05]=$((31 + days[04])) 
    days[06]=$((30 + days[05])) 
    days[07]=$((31 + days[06])) 
    days[08]=$((31 + days[07])) 
    days[09]=$((30 + days[08])) 
    days[10]=$((31 + days[09])) 
    days[11]=$((30 + days[10])) 

    if ((days[11] < julian_day)); then _month="12"; _day=$((julian_day - days[11])); 
    elif ((days[10] < julian_day)); then _month="11"; _day=$((julian_day - days[10])); 
    elif ((days[09] < julian_day)); then _month="10"; _day=$((julian_day - days[09])); 
    elif ((days[08] < julian_day)); then _month="09"; _day=$((julian_day - days[08])); 
    elif ((days[07] < julian_day)); then _month="08"; _day=$((julian_day - days[07])); 
    elif ((days[06] < julian_day)); then _month="07"; _day=$((julian_day - days[06])); 
    elif ((days[05] < julian_day)); then _month="06"; _day=$((julian_day - days[05])); 
    elif ((days[04] < julian_day)); then _month="05"; _day=$((julian_day - days[04])); 
    elif ((days[03] < julian_day)); then _month="04"; _day=$((julian_day - days[03])); 
    elif ((days[02] < julian_day)); then _month="03"; _day=$((julian_day - days[02])); 
    elif ((days[01] < julian_day)); then _month="02"; _day=$((julian_day - days[01])); 
    else 
     _month="01"; _day=${julian_day}; 
    fi 
    echo "${_year}${_month}${_day}" 
} 

Третья функция, date_subtract, принимает григорианскую дату, преобразует его в Julian, делает дату математику, и преобразует обратно в григорианский.

function date_subtract { 
    typeset julian_from_date=$(gregorian_to_julian "$1") 
    typeset number_of_days=$2 
    typeset julian_year=$(echo "${julian_from_date}" | cut -c1-4) 
    typeset julian_days=$(echo "${julian_from_date}" | cut -c5-7) 
    typeset leap_year="FALSE" 
    if ((julian_days - number_of_days > 0)); then 
     ((julian_days -= number_of_days)) 
    else 
     ((julian_year -= 1)) 

     if ((julian_year % 4 == 0)) && ((julian_year % 100 != 0)) || ((julian_year % 400 == 0)); then 
      leap_year="TRUE" 
     fi 
     if [[ "${leap_year}" == "TRUE" ]]; then 
      ((julian_days = julian_days + 366 - number_of_days)) 
     else 
      ((julian_days = julian_days + 365 - number_of_days)) 
     fi 
    fi 
    typeset gregorian_date=$(julian_to_gregorian "${julian_year}${julian_days}") 
    echo "${gregorian_date}" 
} 

EDIT: Следующие работы хорошо на Linux. И намного проще.

Если вам нужна дата, отформатированная как YYMMDDHH, тогда это достаточно просто, как @FrankH. Как отметил в своем комментарии:

date +"%Y%m%d%H" 

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

$ date -d @123456789 
Thu Nov 29 15:33:09 CST 1973 

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

Обратите внимание, что date '+%s' дает нам секунд с эпохи.

$ date -d @$(($(date '+%s') - $((60 * 60 * 24 * 30)))) '+%Y%m%d%H' 
2014011211 

Если вам нужно труба, датирующая строку adb, то вы можете окружить команду с $ (...).

echo $(date -d @$(($(date '+%s') - $((60 * 60 * 24 * 30)))) '+%Y%m%d%H') | adb 
+0

К сожалению, Solaris не имеет даты -d. 'date: незаконный вариант - d' – taylordurden

+0

Извините. Я использовал сервер linux, чтобы проверить это. Я вижу, что Solaris не предоставляет формат '' +% s'', поэтому сбой по нескольким подсчетам. – Gabe

0

Если у вас есть Solaris 11, ответ прост, потому что его ksh является ksh93. Solaris 11 ksh man page имеет эту информацию о printf:

A %(date-format)T format can be use to treat an argument as a date/time string 
and to format the date/time according to the date-format as defined for the 
date(1) command. 

Допустимые строка даты/время форматы не указаны на странице ksh людей, но (несколько), упомянутый в AST tm(3) man page. Принимаются широкий выбор. В частности, это будет делать то, что вы хотите:

$ printf "%(%Y%m%d%H)T\n" 
2014021118 
$ printf "%(%Y%m%d%H)T\n" now 
2014021118 
$ printf "%(%Y%m%d%H)T\n" "30 days ago" 
2014011218 
+0

Данг, мы используем Solaris 10 – taylordurden

Смежные вопросы