3

考虑以下日志文​​件,

FSDFFDSFFDSFDS VCXVCXVCX 3343022340 IT_ON FDSFR0W3EV VXDF03
DDSDS232323SD DSADFSDA SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
DDSDS232323SD DSADFSDA SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
DDSDSDEERWREF FSFDSDFFDS  SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3Q
DDSDS232323SD DSADFSDA SDA32323 SDADSDQ SDAFDSADSDA 
DSADSE3QZCD FFDSFDAREDFS 23FDSFDDS  IT_ON FDSFR0W3EV VXDF03ETRRT
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_OFF FDSFR0W3EV VXDF03ETRRT
DDSDSDEERWREF FSFDSDFFDS  SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
DDSDS232323SD DSADFSDA SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_ON FDSFR0W3EV VXDF03ETRRT
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_OFF FDSFR0W3EV VXDF03ETRRF
DDSDSDEERWREF FSFDSDFFDS  SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
DDSDS232323SD DSADFSDA SDA32323 SDADSDQ SDAFDSADS SDA DSADSE3QZCD
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_ON FDSFR0W3EV VXDF03ETRRT
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_OFF FDSFR0W3EV VXDF03ETRR
FFDSFDAREDFS 23FDSFDDSFK 3343022340 IT_OFF FDSFR0W3EV VXDF03ETRR

我必须计算发生了多少 IT_ON 到 IT_OFF 和 IT_OFF 到 IT_ON 的转换,即

IT_ON to IT_OFF : 3
IT_OFF to IT_ON : 2

我一直在尝试将 *grep "IT_ON"* 和 *grep "IT_OFF"* 与 IF 语句一起使用,但这有点复杂。有什么帮助吗?

4

6 回答 6

1

这是另一种方法:

 grep -Po "IT_(ON|OFF)" inputFile \
 | uniq | paste - - \
 | awk 'NR==1 && NF==2{print;f=1}END{if(f)printf "%3d\t%3d\n", NR,NR-1}'

输出格式:

IT_ON   IT_OFF
  3       2
于 2012-07-10T11:25:58.940 回答
1

假设您的数据文件名为data.log

grep -Eo 'IT_(ON|OFF)' data.log | uniq | tail -n +2 |sort |uniq -c

输出:

3 IT_OFF
2 IT_ON

注释:

grep -Eo 'IT_(ON|OFF)' data.log $(: -E for extended regex, -o to only print matching part ) \
  | uniq                        $(: deduplicate adjacent items ) \
  | tail -n +2                  $(: drop the first line )        \
  | sort | uniq -c              $(: sort , then give a count for each unique item )
于 2012-07-10T15:52:36.070 回答
1
awk '/IT_ON/ {on = 1; if (off) {on_to_off++}; off = 0} /IT_OFF/ {off = 1; if (on) {off_to_on++}; on = 0} END {print "IT_ON to IT_OFF :", on_to_off; print "IT_OFF to IT_ON :", off_to_on}' inputfile

分成多行:

awk '
    /IT_ON/ {
        on = 1; 
        if (off) {
            on_to_off++
        }; 
        off = 0
    } 
    /IT_OFF/ {
        off = 1; 
        if (on) {
            off_to_on++
        }; 
        on = 0
    } 
    END {
        print "IT_ON to IT_OFF :", on_to_off; 
        print "IT_OFF to IT_ON :", off_to_on
    }' inputfile

如果您需要使用一个 ID 来跟踪每个 ID 的转换,那么您可以对数组使用相同的技术。此外,您可能需要在第一次看到它时使用标志来设置 ON 状态,以确保将初始 ON 计为从关闭到打开的转换。

于 2012-07-10T11:06:21.597 回答
0

但是,不完全是您想要的,可能会起作用:

sed -n 's/.*\(IT_ON\|IT_OFF\).*/\1/p' input | uniq > input.tmp
grep $(head -1 input.tmp) input.tmp | uniq -c
expr $(grep $(head -2 input.tmp | tail -1) input.tmp | wc -l) - 1
rm input.tmp
于 2012-07-10T11:24:12.757 回答
0

在 awk 中:

/IT_ON/        { on=1; }
on && /IT_OFF/ { offs++; on=0; off=1; }
off && /IT_ON/ { ons++; off=0; on=1; }
END {
  printf("ON to OFF: %d\nOFF to ON: %d\n", offs, ons);
}

回报:

ON to OFF: 3
OFF to ON: 2

你可以用任何语言实现相同的逻辑,包括 shell,但这对我来说似乎是最干净的。

于 2012-07-10T14:39:47.483 回答
0

这是 bash 中的一个 shell 脚本,可以满足您的要求:

#!/bin/bash

testfile="test.txt"

uniques=$(command grep -o IT_O. $testfile | uniq)
count=$(echo "$uniques" | paste - - | grep -c "IT_O.[[:space:]]IT_O.")

if [[ ${uniques:0:5} = "IT_ON" ]]; then
    echo "IT_ON  -> IT_OFF: $count"
    echo "IT_OFF -> IT_ON : $(($count-1))"
else
    echo "IT_ON  -> IT_OFF: $(($count-1))"
    echo "IT_OFF -> IT_ON : $count"
fi

不幸的是,我不能在测试上花费太多时间——请运行一些试验,看看它是否足够健壮,适合您的用例。

于 2012-07-10T12:52:55.800 回答