شيل / التعابير المنطقية: استخراج عبر خطوط متعددة
سؤال
وأنا أحاول كتابة السيناريو سجل الاعراب لاستخراج الأحداث الفاشلة. يمكنني سحب هذه مع البقرى:
$ grep -A5 "FAILED" log.txt
2008-08-19 17:50:07 [7052] [14] DEBUG: data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 33 :FAILED err:023
2008-08-19 17:50:07 [7052] [14] DEBUG: data: 20 74 65 78 74 3a 20 00 text: .
2008-08-19 17:50:07 [7052] [14] DEBUG: Octet string dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [14] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1158667543, dst=447872123456, type=2
--
2008-08-19 17:50:07 [7052] [8] DEBUG: data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 34 :FAILED err:024
2008-08-19 17:50:07 [7052] [8] DEBUG: data: 20 74 65 78 74 3a 20 00 text: .
2008-08-19 17:50:07 [7052] [8] DEBUG: Octet string dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [8] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1040097716, dst=447872987654, type=2
وما يهمني في هو، لكل كتلة، رمز الخطأ (أي "023" جزء من ": يخطئ فشل: 023" في السطر الأول) وعدد التوقيت الصيفي (أي "447872123456" من "التوقيت الصيفي = 447872123456 "على السطر الأخير).
ويمكن لأي شخص أن يساعد مع قذيفة أونيلينير لاستخراج تلك القيمتين، أو تقديم بعض النصائح عن كيفية وأود أن التعامل مع هذا؟
المحلول
grep -A 5 FAILED log.txt | \ # Get FAILED and dst and other lines
egrep '(FAILED|dst=)' | \ # Just the FAILED/dst lines
egrep -o "err:[0-9]*|dst=[0-9]*" | \ # Just the err: and dst= phrases
cut -d':' -f 2 | \ # Strip "err:" from err: lines
cut -d '=' -f 2 | \ # Strip "dst=" from dst= lines
xargs -n 2 # Combine pairs of numbers
023 447872123456
024 447872987654
وكما هو الحال مع كل قذيفة "واحد" -liners، يكاد يكون من المؤكد هناك طريقة أكثر أناقة للقيام بذلك. ومع ذلك، أجد النهج المتكرر ناجحة جدا للحصول على ما أريد: بدء مع الكثير من المعلومات (البقرى الخاص بك)، ثم تضييق خطوط أريد (مع البقرى)، ثم قص من الأجزاء من كل سطر أريد (مع قطع).
وأثناء استخدام الأدوات لينكس يتطلب المزيد من خطوط، عليك فقط أن تعرف أساسيات بضعة أوامر لتفعل أي شيء تريده. بديل هو استخدام AWK، الثعبان، أو غيرها من لغات البرمجة، والتي تتطلب معرفة البرمجة أكثر تخصصا ولكن سيستغرق أقل مساحة الشاشة.
نصائح أخرى
وهناك حل بسيط في روبي، وهنا filter.rb
:
#! /usr/bin/env ruby
File.read(ARGV.first).scan(/:FAILED\s+err:(\d+).*?, dst=(\d+),/m).each do |err, dst|
puts "#{err} #{dst}"
end
وتشغيله مع:
ruby filter.rb my_log_file.txt
وتحصل عليه:
023 447872123456
024 447872987654
إذا كان هناك دائما نفس العدد من الحقول التي يمكن فقط
grep -A5 "FAILED" log.txt | awk '$24~/err/ {print $24} $12~/dst/{print $12}' error.txt
err:023
dst=447872123456,
err:024
dst=447872987654,
وهذا يتوقف على كيف تبدو بقية الملفات التي قد تكون قادرة على تخطي البقرى كل توجثير.
وو" $ 24 ~ / يخطئ / {طباعة $ 24} م>" جزء يروي AWK إلى رقم الحقل طباعة 24 إذا كان يحتوي يخطئ، ~ / XXX / حيث XXX هو تعبير عادي.