awk命令行和shell脚本中的不同行为

时间:2016-01-17 17:05:08

标签: bash shell awk

我有这个可以正常使用的脚本

#!/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

有谁知道为什么会这样?

2 个答案:

答案 0 :(得分:2)

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

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;}'

答案 1 :(得分:2)

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

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

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