在 awk 字符串中调用 'date' 命令,格式为 +%a

Invoking 'date' command inside awk string, with +%a formatting

该网站还是新手,但这里... 基本上我将事件存储在多个文件中,每个事件都是一行,每行包含日期($1)、开始($2)和停止($3)时间以及其他几条数据。我使用两个双下划线 ("__") 作为字段分隔符。我一直在使用各种 shell 脚本来管理数据,我使用 awk 来计算统计数据,但在调用日期函数时遇到了问题,因此我无法获得一周中的每一天的总数。经过大量修改和扫描讨论板后,我得到了这个:

ls /home/specified/folder/MBRS.db/* |
xargs -n 1 -I % awk -F"__" ' == "CLOSED" &&  >= "'$backDATE'" { print [=11=] }' % |
awk 'BEGIN{FS="__"}{specDATE=system("date --date="" +%a")} specDATE == "Tue" {print " "}'

ls /home/lingotech/Einstein/data/MBRS.db/* |
xargs -n 1 -I % awk -F"__" ' == "CLOSED" &&  >= "'$backDATE'" { print [=12=] }' % |
awk 'BEGIN{FS="__"}system("date --date="" +%a") == "Mon" {print " "}'`

我没有输出开始时间和停止时间,而是为每个条目获取一周中所有不同日期的列表。

我尝试了比我愿意承认的更多的日期用法变体,包括:

for y in Sun Mon Tue Wed Thu Fri Sat; do
  for directory in $( ls /home/specified/directory/MBRS.db/* | xargs -n 1 ); do
    printf "."
    [[ $( cat $directory | awk -F"__" ' == "CLOSED" &&  >= "'$backDATE'" { print  }' | xargs -n 1 -I z date +%a -d z ) == "$y" ]] && echo BLAH
  done
done

如果能对我搞砸的事情做出一些有用的解释,我们将不胜感激。提前致谢。哦,我以 YYMMDD 格式存储日期,但这似乎不是 ubuntu 服务器版本 'date'.

的问题

好的,所以我最终使用了这个:

>backDATE=150000; 
>     for x in $listOFsites; do
>        for y in Sun Mon Tue Wed Thu Fri Sat; do
>            totalHOURS=$( awk 'BEGIN{FS="__"} NF == 10 &&  >= "'$backDATE'" &&  == "'$x'" &&  == "CLOSED" {while ( ( "date +%a -d \"""\"" | getline newDAY) > 0 ){if (newDAY == "'$y'") print " "}}' /home/absolute/path/* | xargs -I % /home/custom/duration/calc % | paste -sd+ | bc ); printf "."; 
>        done
>     done

我必须在单引号内使用日期(以便我可以将 $1 传递给它)而不是在单引号外(使用 -F"__" -v newDAY=...),但在单引号内获取system() 的输出有问题。在看到:How can I pass variables from awk to a shell command? 之后,我终于看到了 while (cmd | get line x) 格式,这是我问题的症结所在。支持埃德·莫顿

我不知道其余的所有内容(对我的阅读口味来说文字太多了!)但是根据您发布的答案,这部分内容:

awk 'BEGIN{FS="__"} NF == 10 &&  >= "'$backDATE'" &&  == "'$x'" &&  == "CLOSED" {while ( "date +%a -d """ | getline newDAY){if (newDAY == "'$y'") print " "}}' /home/absolute/path/*

假设它做你想做的事情会写成:

awk -v backDATE="$backDATE" -v x="$x" -v y="$y" '
    BEGIN { FS="__" }
    (NF == 10) && ( >= backDATE) && ( == x) && ( == "CLOSED") {
        cmd = "date +%a -d \""  "\""
        while ( (cmd | getline newDAY) > 0 ) {
            if (newDAY == y) {
                print , 
            }
        }
        close(cmd)
    }
' /home/absolute/path/*

wrt 为什么使用 awk 变量而不是让 shell 变量扩展成为 shell 脚本主体的一部分,答案是健壮性和简单性。

这是让 shell 变量扩展成为 awk 脚本主体的一部分:

$ x="hello world"
$ awk 'BEGIN{ print '$x' }'
awk: cmd. line:1: BEGIN{ print hello
awk: cmd. line:1:                   ^ unexpected newline or end of string
$ awk 'BEGIN{ print "'$x'" }'
awk: cmd. line:1: BEGIN{ print "hello
awk: cmd. line:1:              ^ unterminated string
awk: cmd. line:1: BEGIN{ print "hello
awk: cmd. line:1:              ^ syntax error
$ awk 'BEGIN{ print "'"$x"'" }'
hello world
$ x="hello
world"
$ awk 'BEGIN{ print "'"$x"'" }'
awk: cmd. line:1: BEGIN{ print "hello
awk: cmd. line:1:              ^ unterminated string
awk: cmd. line:1: BEGIN{ print "hello
awk: cmd. line:1:              ^ syntax error

这是使用一个用 shell 变量的值初始化的 awk 变量:

$ x="hello world"
$ awk -v x="$x" 'BEGIN{ print x }'
hello world

$ x="hello
world"
$ awk -v x="$x" 'BEGIN{ print x }'
hello
world

看出区别了吗?

至于为什么要将命令存储在变量中 - 因为您必须在使用后关闭它,并且它在关闭命令中的拼写方式必须与您打开管道时的拼写方式完全相同。比较:

cmd = "date +%a -d \""  "\""
cmd | getline
close(cmd)

对比:

"date +%a -d \""  "\"" | getline
close("date +%a -d \"" $l "\"")

并花非常接近的时间 l寻找第二个版本中的错误。