2010-11-12 5 views
2

J'ai un fichier avec plusieurs structures de données comme si:en utilisant awk pour vérifier entre deux dates

eventTimestamp: 2010-03-23T07:56:19.166 
result: Allowed 
protocol: SMS 
payload: RCOMM_SMS 

eventTimestamp: 2010-03-23T07:56:19.167 
result: Allowed 
protocol: SMS 
payload: RCOMM_SMS 

eventTimestamp: 2010-03-23T07:56:19.186 
result: Allowed 
protocol: SMS 
payload: SMS-MO-FSM 

eventTimestamp: 2010-03-23T07:56:19.197 
result: Allowed 
protocol: SMS 
payload: COPS 

eventTimestamp: 2010-03-23T07:56:29.519 
result: Blocked 
protocol: SMS 
payload: COPS 
type: URL_IWF 
result: Blocked 

Je veux trouver tous les événements qui sont la charge utile: SMS-MO-États fédérés de Micronésie ou la charge utile: SMS-MO-FSM-INFO qui s'est produite entre les périodes 2010-03-23 ​​12:56:47 et 2010-03-23 ​​13:56:47. Lorsque vous interrogez ce fichier jusqu'à présent, je l'ai utilisé awk de la manière suivante:

cat checkThis.txt | 
awk 'BEGIN{FS="\n"; RS=""; OFS=";"; ORS="\n"} 
    $1~/eventTimestamp: 2010-03-23T14\:16\:35/ && $4~/SMS-MO-FSM-INFO|SMS-MO-FSM$/ {$1=$1 ""; print $0}' 

Ce qui me donnera tous les événements qui se sont produits sur la deuxième 14:16:35 en 2010-03-23. J'ai du mal, cependant, à penser à la façon dont je pourrais mettre la plage de dates dans ma requête. Je pourrais utiliser ce qui suit pour mettre les dates dans le temps de l'époque, mais comment puis-je utiliser ce qui suit dans mon awk pour vérifier si la date se situe entre le temps nécessaire:

python -c "import time; ENGINE_TIME_FORMAT='%Y-%m-%dT%H:%M:%S'; print int(time.mktime(time.strptime('2010-03-23T12:52:52', ENGINE_TIME_FORMAT)))" 

Je sais que cela pourrait faire en Python, mais je écrit un analyseur en Python pour cela et je veux cette méthode comme un vérificateur alternatif, donc je veux utiliser awk si possible.

Je pris un peu plus loin et a créé un script python pour la conversion du temps:

#!/usr/local/bin/python 
import time, sys 
ENGINE_TIME_FORMAT='%Y-%m-%dT%H:%M:%S' 
testTime = sys.argv[1] 
try: 
    print int(time.mktime(time.strptime(testTime, ENGINE_TIME_FORMAT))) 
except: 
    print "Time to convert %s" % testTime 
    raise 

J'ai ensuite essayé d'utiliser getline pour attribuer la conversion à une variable de comparaison:

cat checkThis.txt| awk 'BEGIN {FS="\n"; RS=""; OFS=";"; ORS="\n"; "./firstDate '2010-03-23T12:56:47'" | getline start_time; close("firstDate"); "./firstDate '2010-03-23T13:56:47'" | getline end_time; close("firstDate");} ("./firstDate $1" | getline) > start_time {$1=$1 ""; print $0}' 
Traceback (most recent call last): 
    File "./firstDate", line 4, in <module> 
testTime = sys.argv[1] 
IndexError: list index out of range 

Le getline fonctionne dans le BEGIN et je l'ai vérifié dans l'impression finale mais il semble que j'ai des problèmes dans la partie comparaison du script.

+0

Avez-vous 'gawk'? Il supporte la conversion de datespecs en timestamps en utilisant 'mktime' (vous aurez probablement besoin d'analyser un peu le datespec - convertir les traits d'union, les deux-points et" T "en espaces et supprimer la partie décimale). –

+0

comment le ferais-je en utilisant gawk? – amadain

+0

J'ai essayé d'utiliser awks getline pour faire la conversion de temps, mais je n'arrive pas à l'utiliser dans la partie comparaison du script (voir l'addition au problème original). Je suppose que le même problème se poserait avec gawk – amadain

Répondre

6

L'observation clé est que vous pouvez comparer vos horodatages à l'aide des comparaisons alphanumériques et obtenir la bonne réponse - qui est la beauté de ISO 8601 notation.

Ainsi, adapter votre code légèrement - et la mise en forme pour éviter les barres de défilement:

awk 'BEGIN { 
     FS = "\n" 
     RS = "" 
     OFS = ";" 
     ORS = "\n" 
     t1 = "2010-03-23T07:45:00" 
     t2 = "2010-03-23T08:00:00" 
     m1 = "eventTimestamp: " t1 
     m2 = "eventTimestamp: " t2 
     } 
$1 ~ /eventTimestamp:/ && $4 ~ /SMS-MO-FSM(-INFO)?$/ { 
    if ($1 >= m1 && $1 <= m2) print $1, $2, $3, $4; 
}' "[email protected]" 

De toute évidence, vous pouvez mettre cela dans un fichier de script - vous ne voulez pas taper souvent. Et obtenir la plage de dates saisie avec précision et commodité est l'une des parties difficiles. Notez que j'ai ajusté la plage de temps pour correspondre aux données.

Lorsqu'il est exécuté sur les données de l'échantillon, il émet un enregistrement:

eventTimestamp: 2010-03-23T07:56:19.186;result: Allowed;protocol: SMS;payload: SMS-MO-FSM 
1

Un peu un kludge, mais ce script suppose que vous avez la commande unix "date". Également codé en dur vos horodateurs de début et de fin dans le bloc BEGIN. Notez que les données de test répertoriées ci-dessus ne correspondent pas aux heures de début et de fin de l'échantillon.

#!/usr/bin/awk -f 
BEGIN { 
     command="date -f\"%s\" -d \"2010-03-23 12:56:47\""; command | getline startTime; close(command) 
     command="date -f\"%s\" -d \"2010-03-23 13:56:47\""; command | getline endTime; close(command) 
} 

$0 ~ /^eventTimestamp:/ { 
     command="date -f\"%s\" -d " $2; command | getline currTime; close(command) 

     if (currTime >= startTime && currTime <= endTime) { 
       printIt="true" 
     }else{ 
       printIt="false"; 
     } 
} 

printIt == "true" { print }    
+0

Comme je n'ai pas encore assez de réputation pour voter, je ne peux pas voter pour la solution de Jonathan Leffler. Mais c'est un bon. – cryptochaos

Questions connexes