Синтаксис для использования времени эпох в вычислениях с использованием `--date = STRING` команды` date`

Я изучаю bash скриптинг в данный момент, и это казалось превосходной простой задачей для практики с, поэтому я написал следующее. (Мой другой ответ дает простой хак расширения истории, но это полный сценарий, и я счел его достойным сделать дополнительный ответ.) Я считаю, что это POSIX совместимо и должно работать с # !/bin/sh , но не 100% уверен. EDIT: Фактически = ~ несовместим с POSIX. Вы можете взять эту выписку и позволить вырезать вернуть ошибку, хотя.

#!/bin/bash

fieldtocut=1
delimiter=','

usage () {
    cat << EOF
usage: $0 [-f FIELD] [-d DELIMITER] file1..
Cuts field FIELD from each file and pastes it.
Default field is 1, default delimiter is ','
EOF
    exit $1
}

while getopts ':f:d:' opt ; do
    case $opt in
        f)
            if [[ $OPTARG =~ ^[0-9]+$ ]] ; then
                fieldtocut="$OPTARG"
            else
                usage 1
            fi
            ;;
        d)
            delimiter=$OPTARG
            ;;
        *)
            usage 1
            ;;
    esac
done
shift $((OPTIND-1))

[ $# -eq 0 ] && usage 0

pasteargs=''

for file in "$@" ; do
    pasteargs=$(printf '%s' "$pasteargs" '<(cut -d$delimiter -f$fieldtocut ' "$file" ') ')
done

eval paste $pasteargs

-121--53856-

Вы можете автоматизировать это с помощью глоббинга, в частности, квалификатора e glob , плюс eval , но это не очень красиво, и цитирование является сложным:

eval paste *.csv(e\''REPLY="<(cut -d, -f1 $REPLY)"'\')
  • Часть между \' ...\' является некоторым кодом для выполнения для каждого совпадения с глобусом. Он выполняется с переменной REPLY , набора к совпадению, и может изменить его.
  • Я помещаю код в одинарные кавычки, чтобы он не разворачивался при разборе глобуса.
  • Код REPLY = « создает последовательность , если соответствует file1.csv . Двойные кавычки необходимы для того, чтобы часть после знака равенства не разворачивалась при выполнении кода e отдельно от подстановки значения REPLY .
  • Поскольку каждый файл с глоббедом заменен последовательностью,

Было бы лучше скрыть сложность функции. Минимально протестирован.

function map {
  emulate -LR zsh
  local cmd pre
  cmd=()
  while [[ $# -ne 0 && $1 != "--" ]]; do
    cmd+=($1)
    shift
  done
  if ((!$#)); then
    echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
    return 125
  fi
  shift
  while [[ $# -ne 0 && $1 != "--" ]]; do
    pre+="${(q)1} "
    shift
  done
  if ((!$#)); then
    echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
    return 125
  fi
  shift
  eval "${(@q)cmd}" "<($pre${(@q)^@})"
}

Пример использования (синтаксис напоминает zargs ):

map paste -- cut -d, -f1 -- *.csv

-121--53853-

Bash не записывает свою историю в файл истории, пока не завершит его или вы явно не вызовете history -w . Так что если вы только что добавили свой пароль в историю текущей оболочки, он еще не был записан в .bash _ history , он просто сидит там в памяти. Для просмотра списка последних команд можно запустить fc -l , затем history -d для удаления записи.

$ echo swordfish
swordfish
Oops, that was my password!
$ fc -l -2
1234 ls
1235 echo swordfish
$ history -d 1235
$ fc -l -3
1234 ls
1235 fc -l -2
1236 history -d 1236

Если файл истории уже написан (например, из-за наличия history -w в PROMPT _ COMMAND или ловушки отладки), выполните это действие и отредактируйте .bash _ history .

Если вы хотите забыть историю текущей оболочки, отмените установку HISTFILE и убедитесь, что она не установлена до выхода из оболочки. Если вы хотите забыть текущую историю до этого момента, но начать запись, вы можете вызвать history -c . Если вы хотите забыть все записи истории 3, кроме последних, установите значение HISTFILE = 3 , затем (в отдельной командной строке) вернитесь к обычному значению.

2
29.04.2018, 20:51
2 ответа

Вы можете поместить вычисление в круглые скобки...

root@beaglebone:~/bbbrtc# date -d "@1524884843+(1 month)"
Sat Apr 28 03:07:23 UTC 2018
0
27.01.2020, 22:32

С помощью ast -open date(, возможно, встроенная дата ksh93, в зависимости от того, как он был построен, и среды):

$ date -d '#1234567890'
Fri Feb 13 23:31:30 GMT 2009
$ date -d "#1234567890 30 days"
Sun Mar 15 23:31:30 GMT 2009

(ast dateне поддерживает смещения, выраженные в месяцах (месяцы не имеют фиксированной длины )).

В GNU dateвы можете использовать старый метод (до того, как @epochбыла добавлена ​​поддержка ), где вы выражаете время эпохи как смещение в секундах относительно 1970 года -01 -01 00 :00 :00 UTC:

$ date -d '1970-01-01T00:00:00Z + 1234567890 seconds'
Fri 13 Feb 23:31:30 GMT 2009
$ date -d '1970-01-01T00:00:00Z + 1234567890 seconds + 1 month'
Mon 16 Mar 23:31:30 GMT 2009

Обратите внимание, однако, что здесь 1 месяц равен 31 дню , предположительно потому, что dateсчитает, что смещение 1 месяц относится к январю 1970 года.

Если ваш dateотносится к GNU, и вы хотели бы, чтобы он продемонстрировал поведение для месяцев -относительных дат, при котором смещение в один -месяц дает вам тот же день месяца (при условии, что существует такое день в следующем месяце )совпадает с начальной датой (, хотя и не обязательно в тот же час дня, если в интервале )произошло какое-то изменение летнего времени, тогда вы, вероятно, захотите использовать @ двухэтапный подход Исаака .

0
27.01.2020, 22:32

Теги

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