【问题标题】:awk different behaviour in command line and in shell scriptawk 在命令行和 shell 脚本中的不同行为
【发布时间】:2016-01-17 17:05:08
【问题描述】:

我有这个运行良好的脚本

#!/bin/bash
if [ $# -lt 1 ]
then
  echo "USAGE: `basename $0` username"
  exit 1
fi

logins=`last | grep $1`
times=`echo "$logins" | awk '{print $10}'`
timesCleared=`echo "$times" | sed -e 's/(//' -e 's/)//'`
minutes=`echo "$timesCleared" | awk -F: '{ print $1*60+$2}'`
total=0
for m in $minutes
do
  total=$(( $total + $m ))
done

echo $total > out.txt
cat out.txt

但是,例如,当我在交互式 shell 中尝试此命令时,它不起作用( echo $minutes 给出不同的输出):

echo "in 02:16 00:28 00:16 00:25 02:44 00:09" | awk -F: '{ print $1*60+$2;}'

打印 16

如果我在脚本中写 echo $minutes 它会给我正确的输出:

0 136 28 16 25 164 9

有人知道这是为什么吗?

【问题讨论】:

  • 看起来应该有一些转义......如果不是美元符号,那么它是数学运算符,+ - * /。
  • in 作为数字没有意义,因此被评估为零。 (是的,有一个数字后缀,但这就是这里发生的事情。)
  • 另外,我得到的一些行包含3+23:27之类的字符串。

标签: bash shell awk


【解决方案1】:

脚本中的变量包含换行符,这很重要。在分配给变量minutes 的行中发送到awk 的内容不是

in 02:16 00:28 00:16 00:25 02:44 00:09

就像在你的命令行中一样,而是

in
02:16
00:28
00:16
00:25
02:44
00:09

在第一种情况下,awk 将$1 视为in 02,将$2 视为16 00。在第二种情况下,它单独在每一行上工作。当 awk 将字符串转换为数字时,它只使用字符串的第一个字符;如果它在开头没有找到数字(如字符串in 02),则将其转换为0,而不会出现任何错误消息。

您可以使用RS awk 伪变量将记录分隔符设置为空格:

echo "in 02:16 00:28 00:16 00:25 02:44 00:09" |
    awk -F: -v RS=' ' '{ print $1*60+$2;}'

或者,您可以使用换行符来回显字符串:

echo "in
02:16
00:28
00:16
00:25
02:44
00:09" | awk -F: '{ print $1*60+$2;}'

【讨论】:

    【解决方案2】:

    脚本中你echo的字符串是换行符分隔的,不是空格分隔的;所以您以交互方式尝试的命令并没有做同样的事情。

    要重现脚本中发生的事情,请尝试

    echo "in 02:16 00:28 00:16 00:25 02:44 00:09" |
    tr ' ' '\n' |
    awk -F: '{ print $1*60+$2;}'
    

    【讨论】:

    • 是的,我怀疑它可能是格式。这行得通:)
    猜你喜欢
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 2018-08-28
    • 1970-01-01
    • 2018-04-02
    相关资源
    最近更新 更多