Синтаксическая ошибка с expr в bash - PullRequest
1 голос
/ 24 декабря 2011

Я пытаюсь получить первый день следующего квартала, например, сейчас я хотел бы получить 00:01 2012-01-01. Это не должно быть слишком сложно. Но я застрял с синтаксической ошибкой, потому что мне не удается все правильно избежать.

Чтобы получить правильный месяц, который я хочу использовать:

expr `date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1"`

Деталь ( %m - 1 ) / 3 + 1 рассчитывает номер текущего квартала. Тем не менее, * кажется, что-то там не так. Если я заменю его на +, синтаксическая ошибка не возникнет (результат мне просто не интересен ...). Я пытался сбежать * с помощью \*, но это не помогло. Я полагаю, что есть некоторые проблемы с обратными чертами.

Как мне правильно избежать *?

Edit: Моя проблема уже решена, но я хочу добавить короткое предупреждение для других . Обратите внимание, что вам нужно будет добавить также ведущие нули для месяца, если вы хотите использовать его непосредственно в дате и заботиться о правильном году. Так что в конце дня предложение Паксдиабло, вероятно, самое простое.

Ответы [ 5 ]

3 голосов
/ 24 декабря 2011

Если вы не возражаете закодировать функцию bash для этого, вы можете использовать что-то вроде следующей функции getNextQuarter:

# getNextQuarter - returns YYYY-MM-DD for the first day of the next quarter.
getNextQuarter() {
    m="$(date +%m)"
    case $m in
        '01' | '02' | '03') echo "$(date +%Y)-04-01" ;;
        '04' | '05' | '06') echo "$(date +%Y)-07-01" ;;
        '07' | '08' | '09') echo "$(date +%Y)-10-01" ;;
        '10' | '11' | '12') echo "$(expr $(date +%Y) + 1)-01-01" ;;
    esac
}

nq=$(getNextQuarter)
echo $nq

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

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

Подумайте о том, что другие (или даже вы через шесть месяцев) подумают о вашем коде при его просмотре. Мне нравится жить в предположении, что те, кто должен поддерживать мой код, - это психопаты, которые знают, где я живу.

2 голосов
/ 24 декабря 2011
$ date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1" | xargs expr
1
1 голос
/ 24 декабря 2011

Первая проблема заключалась в том, что * считался подстановочным знаком после вывода по дате.Я решил это, используя $[] (эквивалент $(())) вместо из expr.

Вторая проблема (по крайней мере, здесь, в Mac OS X) заключается в том, что '%'необходимо экранировать, используя '%%' (это действительно для всех версий даты):

$ echo $(($(date "+( ( %m - 1 ) / 3 + 1 ) * 3 %% 12 + 1")))
1

Альтернативой, которую я нашел, было использование eval после правильного экранирования скобок:

$ eval "expr $(date "+\( \( %m - 1 \) / 3 + 1 \) '*' 3 %% 12 + 1")"

Обе альтернативы могут быть дополнены нулями, используя printf:

$ printf "%02d\n" $(($(date "+( ( %m - 1 ) / 3 + 1 ) * 3 %% 12 + 1")))
01
$ printf "%02d\n" $(eval "expr $(date "+\( \( %m - 1 \) / 3 + 1 \) '*' 3 %% 12 + 1")")
01
1 голос
/ 24 декабря 2011

Вы можете отключить расширение глоба, используя set, выполнить вычисления и снова включить расширение глоба:

set -o noglob
expr `date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1"`
set +o noglob
0 голосов
/ 24 декабря 2011

Окружите все свое выражение двойными кавычками: проблема в том, что в подстановке команд есть пробелы, что не радует expr.

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

fge@erwin ~ $ expr "`date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1"`"
( ( 12 - 1 ) / 3 + 1 ) * 3 % 12 + 1
fge@erwin ~ $ echo $(($(expr "`date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1"`")))
1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...