Как отобразить строки x-3 и x-1 в зависимости от содержимого строки x? - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть файл, который содержит следующее содержание.я хочу извлечь из него два поля, т.е. 1-е поле (2019-04-09T05: 25: 26) перед словом «Running» и 3-е поле (run_stat) перед «Running»

demo.log

"$id": "9",
"TaskExecId": 7917159,
"WorkflowExecId": 2560888,
"TaskId": 215537,
"TaskName": "run_stat", ------   3rd field
"TaskTypeId": "Custom",
"StartDate": "2019-04-23T05:25:26", -- 1st field
"ExecStatusId": "Running",
"HasStep": 0.0,
"HasTaskExecLog": 0.0,
"HasTaskExecReport": 0.0

Я написал приведенный ниже скрипт, но он не работает.

#!/bin/bash
a=$( date "+%Y-%m-%d %H%M%S" )
b=`sed -n -e '/Running/{x;$!N;p;D;}' -e h demo.log| sed -e 's/ //g;N;s/\n/~/g;s/"//g;s/ //g;s/,//g;s/[a-z]//g;s/[A-Z]//g;s/_//g;s/://g;s/~0.0//g'`
c=$((a-b))
echo $a
echo $b
echo $c

Ожидаемое значение должно отображаться ниже:

run_stat
<current datetime> - 2019-04-23 05:25:26

Ответы [ 5 ]

0 голосов
/ 25 апреля 2019

попробовал на GNU SED

sed -Ez 's/.*\n(([^\n]+\n){3})"\S+":\s*"Running".*/\1/;h;s/[^:]+:\s*"(\S+)".*/\1\n/p;g;s/.*\n[^:]+:\s*"(\S+)".*/\1/' demo.log
0 голосов
/ 25 апреля 2019

Когда у вас есть пары имя-значение, лучше всего сначала заполнить массив этого отображения (f[] ниже), а затем вы можете просто получить доступ к значениям по их именам:

$ cat tst.awk
BEGIN {FS="^[[:space:]]*\"|\"[[:space:]]*:[[:space:]]+\"?|\"?,?[[:space:]]*$"; OFS=" - "}
$1 == "$id" { prt() }
{ f[$2] = $3 }
END { prt() }

function prt() {
    if ( f["ExecStatusId"] == "Running" ) {
        sub(/T/," ",f["StartDate"])
        print f["TaskName"]
        print now, f["StartDate"]
    }
    delete f
}

$ awk -v now="$(date +'%Y-%m-%d %T')" -f tst.awk file
run_stat
2019-04-24 19:59:38 - 2019-04-23 05:25:26
0 голосов
/ 24 апреля 2019

Awk, вероятно, лучший инструмент для этого. Вы можете сохранить историю предыдущих 3 строк, а затем работать с ними при необходимости:

gawk -v "d=$(gdate "+%Y-%m-%d %H%M%S")" '
    /^"ExecStatusId": "Running"/ {
        match(l3, /"TaskName": "(.*)",/, a)
        print a[1]

        match(l1, /"StartDate": "(.*)",/, a)
        print d"-"a[1]
    }
    {l3=l2; l2=l1; l1=$0;}
' demo.log
0 голосов
/ 24 апреля 2019

Проверено в GNU AWK & Sed:

grep -B3 'Running' file.txt | awk '/TaskName/ {print $2} /StartDate/ {print "current datetime - " $2}' | sed -e 's/[",]//g'

Выход:

run_stat
current datetime - 2019-04-23T05:25:26
0 голосов
/ 24 апреля 2019

Более сложный, но менее изнурительный, возможно -

#! /bin/bash

bare() { 
  x="$1"
  x=${x%?,*}   # assuming the exact format shown, 
  x=${x##*: ?} # these strip the quotes and everything outside them
  echo "$x"
}

declare -i ndx=0
declare -a log
while read line
do [[ "$line" =~ Running ]] && break
   log[ndx++]="$line"
done < demo.log

bare "${log[ndx-3]}" # run_stat

y=$( bare "${log[ndx-1]}" )
start=$( date -d "$y" +%s )
now=$( date +%s )
echo $(( now - start ))

Разница выпадает в считанные секунды.

Надеюсь, вы могли бы экстраполировать это на ваши обстоятельства.

...