كيف يمكنني استخدام باش (grep/sed/الخ) للاستيلاء على قسم من السجل بين 2 الطوابع?

StackOverflow https://stackoverflow.com/questions/827930

سؤال

لدي مجموعة من سجلات البريد:البريد.سجل البريد.السجل.0 mail.log.1.gz mail.log.2.gz

كل من هذه الملفات تحتوي على زمنيا فرز الخطوط التي تبدأ مع الطوابع الزمنية مثل:

3 مايو 13:21:12 ...

كيف يمكنني بسهولة الاستيلاء على كل تسجيل دخول بعد فترة معينة من التاريخ/الوقت و قبل آخر تاريخ/وقت باستخدام باش (وما يتصل بها من أدوات سطر الأوامر) دون مقارنة كل سطر واحد ؟ نضع في اعتبارنا أن بلدي قبل وبعد مواعيد قد لا تتطابق تماما مع أي إدخالات في logfiles.

يبدو لي أن كنت بحاجة إلى تحديد إزاحة السطر الأول أكبر من انطلاق الزمني ، إزاحة السطر الأخير أقل من إنهاء الطابع الزمني و قطع هذا القسم بطريقة ما.

هل كانت مفيدة؟

المحلول 2

هنا الفكرة الأساسية من كيفية القيام بذلك:

  1. دراسة الختم على الملف لمعرفة ما إذا كان هو أفضل
  2. إذا كان يمكن أن تكون ذات الصلة, فك الضغط عن الملف إذا لزم الأمر ودراسة أول و آخر خطوط الملف لمعرفة ما إذا كان يحتوي على بدء أو انتهاء الوقت.
  3. إذا كان كذلك, استخدام وظيفة العودية لتحديد ما إذا كان يحتوي على وقت البدء في الأول أو النصف الثاني من الملف.باستخدام وظيفة العودية أعتقد أنك يمكن أن تجد أي تاريخ في مليون خط السجل مع حوالي 20 المقارنات.
  4. صدى السجل(s) في أمر من إزاحة أول دخول إلى إزاحة آخر دخول (لا مزيد من المقارنات)

ما لا أعرفه هو:كيفية قراءة أقصى سطر من ملف (مدى فعالية هو استخدام ذيل n+**n|head 1**?)

أي مساعدة ؟

نصائح أخرى

تحويل مين/ماكس التواريخ في "ثانية منذ العصر" ،

MIN=`date --date="$1" +%s`
MAX=`date --date="$2" +%s`

تحويل أول n الكلمات في كل سطر السجل إلى نفسه ،

L_DATE=`echo $LINE | awk '{print $1 $2 ... $n}'`
L_DATE=`date --date="$L_DATE" +%s`

قارن ورمي بعيدا الخطوط حتى تصل إلى MIN,

if (( $MIN > $L_DATE )) ; then continue ; fi

قارن وطباعة الخطوط حتى تصل إلى MAX,

if (( $L_DATE <= $MAX )) ; then echo $LINE ; fi

الخروج عند تجاوز MAX.

if (( $L_DATE > $MAX )) ; then exit 0 ; fi

النص كاملا minmaxlog.sh يبدو مثل هذا ،

#!/usr/bin/env bash

MIN=`date --date="$1" +%s`
MAX=`date --date="$2" +%s`

while true ; do
    read LINE
    if [ "$LINE" = "" ] ; then break ; fi

    L_DATE=`echo $LINE | awk '{print $1 " " $2 " " $3 " " $4}'`
    L_DATE=`date --date="$L_DATE" +%s`

    if (( $MIN > $L_DATE  )) ; then continue ; fi
    if (( $L_DATE <= $MAX )) ; then echo $LINE ; fi
    if (( $L_DATE >  $MAX )) ; then break ; fi
done

ركضت على هذا الملف minmaxlog.المدخلات,

May 5 12:23:45 2009 first line
May 6 12:23:45 2009 second line
May 7 12:23:45 2009 third line
May 9 12:23:45 2009 fourth line
June 1 12:23:45 2009 fifth line
June 3 12:23:45 2009 sixth line

مثل هذا ،

./minmaxlog.sh "May 6" "May 8" < minmaxlog.input

يجب أن ننظر في كل سطر واحد في مجموعة تريد (أن تقول إذا كان في مجموعة تريد) لذلك أنا التخمين تعني ليس كل سطر في الملف.في الحد الادنى ، سيكون لديك أن ننظر إلى كل سطر في الملف بما في ذلك أول واحد خارج النطاق الخاص بك (أنا أفترض الخطوط في التاريخ/الوقت النظام).

هذا هو بسيطة الى حد كبير نمط:

state = preprint
for every line in file:
    if line.date >= startdate:
        state = print
    if line.date > enddate:
        exit for loop
    if state == print:
        print line

يمكنك كتابة هذا في awk, Perl, Python, حتى COBOL إذا كان يجب ولكن المنطق هو نفسه دائما.

تحديد خط الأعداد الأولى (مع القول grep) ثم عمياء طبع هذا الخط مجموعة لا يساعد منذ البقرى أيضا أن ننظر في جميع الخطوط (كل منهم, ليس فقط ما يصل إلى أول خارج نطاق الأرجح مرتين, واحد أول خط واحد آخر).

إذا كان هذا هو شيء كنت تنوي القيام به في كثير من الأحيان, قد ترغب في النظر في تحويل الجهد من 'في كل مرة كنت تفعل ذلك' إلى 'مرة واحدة ، عندما يكون الملف استقرت'.على سبيل المثال سيكون لتحميل ملف السجل خطوط في قاعدة البيانات مفهرسة حسب التاريخ/الوقت.

أن يستغرق بعض الوقت للحصول على اقامة ولكن سوف يؤدي الاستفسارات الخاصة بك أصبحت أسرع كثيرا.أنا لست بالضرورة الدعوة إلى قاعدة البيانات - ربما يمكن تحقيق نفس التأثير عن طريق تقسيم ملفات السجل في كل ساعة سجلات بالتالي:

2009/
  01/
    01/
      0000.log
      0100.log
      : :
      2300.log
    02/
    : :

ثم لوقت معين, كنت أعرف بالضبط من أين تبدأ و التوقف عن النظر.مجموعة 2009/01/01-15:22 من خلال 2009/01/05-09:07 من شأنه أن يؤدي إلى:

  • بعض (الجزء الأخير) من الملف 2009/01/01/1500.txt.
  • جميع الملفات 2009/01/01/1[6-9]*.txt.
  • جميع الملفات 2009/01/01/2*.txt.
  • جميع الملفات 2009/01/0[2-4]/*.txt.
  • جميع الملفات 2009/01/05/0[0-8]*.txt.
  • بعض (أول جزء) من الملف 2009/01/05/0900.txt.

من كتابة السيناريو إلى عودة تلك الخطوط بدلا من محاولة القيام بذلك يدويا في كل مرة.

ربما يمكنك أن تجرب هذا:

sed -n "/BEGIN_DATE/,/END_DATE/p" logfile

قد يكون من الممكن في باش البيئة ولكن يجب أن تأخذ حقا الاستفادة من الأدوات التي لديها أكثر من المدمج في دعم العمل مع سلاسل والتواريخ.فعلى سبيل المثال روبي يبدو أن لديها المدمج في القدرة على تحليل تنسيق التاريخ.ومن ثم يمكن تحويل للمقارنة بسهولة Unix Timestamp (ايجابي في عدد صحيح يمثل الثواني منذ العصر).

irb> require 'time'
# => true

irb> Time.parse("May 3 13:21:12").to_i
# => 1241371272  

ثم يمكنك بسهولة كتابة روبي النصي:

  • بداية ونهاية التاريخ.تحويل هؤلاء إلى هذا Unix Timestamp عدد.
  • مسح ملفات السجل سطرا سطرا, تحويل التاريخ إلى Unix Timestamp والتحقق من إذا كان ذلك في نطاق تواريخ البدء والانتهاء.

ملاحظة:تحويل إلى Unix Timestamp صحيح الأول هو لطيف لأنه مقارنة الأعداد الصحيحة هي سهلة وفعالة جدا القيام به.

ذكرت "دون مقارنة كل سطر واحد." ه يذهب أن يكون من الصعب "تخمين" في في ملف السجل من الإدخالات يبدأ كونها قديمة جدا أو جديدة جدا دون التحقق من جميع القيم في بين.ومع ذلك ، إذا كان هناك بالفعل زيادة مفردة النغمة الاتجاه ، ثم تعرف على الفور عندما وقف تحليل الخطوط ، لأنه بمجرد الإدخال التالي هو جديد جدا (أو القديمة ، اعتمادا على تخطيط البيانات) كنت أعلم أنك يمكن أن تتوقف عن البحث.لا يزال هناك مشكلة في العثور على السطر الأول في النطاق المطلوب.


أنا فقط لاحظت تحرير الخاص بك.هنا هو ما أود أن أقول:

إذا كنت حقا قلق بكفاءة وجدت أن بداية ونهاية الدخول, ثم هل يمكن أن تفعل الثنائية البحث عن كل.أو إذا كان هذا يبدو مبالغة أو صعبة جدا مع باش أدوات هل يمكن أن يكون الكشف عن مجريات الأمور من القراءة فقط 5% من خطوط (1 من كل 20), الحصول بسرعة على مقربة من الاجابة ثم تكرير ذلك إذا رغبت في ذلك.هذه هي فقط بعض الاقتراحات لتحسين الأداء.

أعلم أن هذا الموضوع قديم ولكن أنا فقط تعثرت على ذلك مؤخرا بعد العثور على سطر واحد حل احتياجاتي:

awk -v ts_start="2018-11-01" -v ts_end="2018-11-15" -F, '$1>=ts_start && $1<ts_end' myfile

في هذه الحالة ، ملف السجلات مع قيم مفصولة بفواصل و الزمني في الحقل الأول.يمكنك استخدام أي صالحة تنسيق الطابع الزمني لبداية ونهاية الطوابع الزمنية ، واستبدال هذه شل المتغيرات إذا رغبت في ذلك.

إذا كنت تريد أن تكتب إلى الملف الجديد, مجرد استخدام عادي إعادة توجيه الإخراج (> newfile) إلحاق نهاية أعلاه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top