bash中带有expr的语法错误

时间:2011-12-24 11:59:19

标签: linux bash shell

我正试图获得下一个四分之一的第一天,例如现在我想得到00:01 2012-01-01。这应该不会太难。但是我遇到了语法错误,因为我无法正确地逃避一切。

要获得我想要使用的正确月份:

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

部分( %m - 1 ) / 3 + 1计算当前四分之一的数量。 但是,*似乎在某种程度上是错误的。如果我用+替换它,则没有语法错误(结果对我来说没有意义......)。我尝试使用*来逃避\*,但这没有用。我认为反引号存在一些问题。

如何正确逃避*

修改 我的问题已经解决,但我想为其他人添加短警告。请注意,如果要在日期中直接使用它并且还要关注正确的年份,则需要在月份中添加前导零。所以在一天结束时,paxdiablo的建议可能是最简单的。

5 个答案:

答案 0 :(得分:3)

如果您不介意编写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

即使在shell脚本中,您也应该考虑使用命名良好的函数而不是可能隐藏的单行程序可以获得的可读性改进。

现在可能不会很快,但说实话,如果速度是你的主要关注点,我还是会重新审视shell脚本。

想一想其他人(或者甚至是你现在六个月后)在查看时会想到你的代码。我喜欢假设那些必须维护我的代码的人是那些知道我住在哪里的精神病患者。

答案 1 :(得分:2)

$ date "+( ( %m - 1 ) / 3 + 1 ) * 3 % 12 + 1" | xargs expr
1

答案 2 :(得分:1)

您可以使用set禁用glob扩展,运行计算并重新启用glob扩展:

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

答案 3 :(得分:1)

第一个问题是*在按日期输出后被视为通配符。我使用$[](相当于$(())代替 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

答案 4 :(得分:0)

用双引号括起你的整个表达式:问题是你的命令替换中有空格,不能取悦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