هل هناك أداة مساعدة لنظام Unix لإضافة الطوابع الزمنية مسبقًا إلى stdin؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

انتهى بي الأمر بكتابة برنامج نصي سريع لهذا الغرض في بايثون، لكنني كنت أتساءل عما إذا كانت هناك أداة يمكنك تغذية النص بها والتي من شأنها أن تسبق كل سطر ببعض النص - في حالتي المحددة، طابع زمني.من الناحية المثالية، سيكون الاستخدام شيئًا مثل:

cat somefile.txt | prepend-timestamp

(قبل أن تجيب على sed، جربت هذا:

cat somefile.txt | sed "s/^/`date`/"

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

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

المحلول

يمكن أن تحاول استخدام awk:

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'

ربما تحتاج إلى التأكد من ذلك <command> ينتج إخراجًا مخزّنًا للخط، على سبيل المثال.يقوم بمسح تيار الإخراج الخاص به بعد كل سطر؛الطابع الزمني awk سيكون وقت الإضافة هو الوقت الذي تظهر فيه نهاية السطر على أنبوب الإدخال الخاص به.

إذا أظهر awk أخطاء، فحاول gawk بدلاً من.

نصائح أخرى

ts من com.moreutils سيضيف طابعًا زمنيًا لكل سطر من المدخلات التي تقدمها له.يمكنك تنسيقه باستخدام strftime أيضًا.

$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$ 

لتثبيته:

sudo apt-get install moreutils

علق, ، متاح عبر هذا الرابط أو كما annotate-output في ديبيان devscripts طَرد.

$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0

قم بتقطير الإجابات المقدمة إلى أبسط إجابات ممكنة:

unbuffer $COMMAND | ts

في Ubuntu، تأتي هذه العناصر من حزم توقع التطوير وmoreutils.

sudo apt-get install expect-dev moreutils

وماذا عن هذا؟

cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'

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

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps

فقط سأرمي هذا هناك:هناك زوج من المرافق في com.daemontools مُسَمًّى tai64n و tai64nlocal التي تم إجراؤها للطوابع الزمنية المعلقة لتسجيل الرسائل.

مثال:

cat file | tai64n | tai64nlocal

إجابة كيرون هي الأفضل حتى الآن.إذا كانت لديك مشاكل لأن البرنامج الأول يقوم بالتخزين المؤقت، يمكنك استخدام برنامج unbuffer:

unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

يتم تثبيته افتراضيًا على معظم أنظمة Linux.إذا كنت بحاجة إلى بنائه بنفسك، فهو جزء من الحزمة المتوقعة

http://expect.nist.gov

استخدم أمر القراءة (1) لقراءة سطر واحد في كل مرة من الإدخال القياسي، ثم إخراج السطر المضاف إليه التاريخ بالتنسيق الذي تختاره باستخدام التاريخ (1).

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp

أنا لست من محبي يونكس، ولكن أعتقد أنه يمكنك استخدامه

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt
#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

إليك الحل المحرج (من نظام Windows/XP مع أدوات MKS المثبتة في الدليل C:\bin).إنه مصمم لإضافة التاريخ والوقت الحاليين بالصيغة mm/dd hh:mm إلى بداية كل سطر بعد جلب هذا الطابع الزمني من النظام أثناء قراءة كل سطر.يمكنك بالطبع استخدام نمط BEGIN لجلب الطابع الزمني مرة واحدة وإضافة هذا الطابع الزمني إلى كل سجل (كل نفس).لقد قمت بذلك لوضع علامة على ملف السجل الذي تم إنشاؤه لـ stdout باستخدام الطابع الزمني في وقت إنشاء رسالة السجل.

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

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

يجب أن يعمل هذا على أنظمة Linux/UNIX أيضًا، فقط تخلص من C\:\\bin\\ الذي يترك السطر

             "date '+%m/%d %R'" | getline timestamp;

هذا، بالطبع، يفترض أن الأمر "date" ينقلك إلى أمر عرض/ضبط تاريخ Linux/UNIX القياسي بدون معلومات مسار محددة (أي أنه تم تكوين متغير PATH للبيئة الخاصة بك بشكل صحيح).

خلط بعض الإجابات أعلاه من natevw وفرانك تش.ايجلر.

تحتوي على ميلي ثانية، وتعمل بشكل أفضل من استدعاء خارجي date يمكن العثور على الأمر في كل مرة وPerl في معظم الخوادم.

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday);
  use POSIX qw(strftime);
  ($s,$ms) = gettimeofday();
  print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
  '

نسخة بديلة مع التدفق والقراءة في حلقة:

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday); use POSIX qw(strftime);
  $|=1;
  while(<>) {
    ($s,$ms) = gettimeofday();
    print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
  }'
$ cat somefile.txt | sed "s/^/`date`/"

يمكنك القيام بذلك (مع جنو/السيد):

$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"

مثال:

$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2

وبطبيعة الحال، يمكنك استخدام الخيارات الأخرى للبرنامج تاريخ.فقط استبدل date +%T مع ما تحتاجه.

يمكن تشغيل إجابة caerwyn كإجراء فرعي، مما قد يمنع العمليات الجديدة في كل سطر:

timestamp(){
   while read line
      do
         echo `date` $line
      done
}

echo testing 123 |timestamp

تنصل:الحل الذي أقترحه ليس أداة مساعدة مدمجة في Unix.

لقد واجهت مشكلة مماثلة منذ بضعة أيام.لم يعجبني بناء الجملة والقيود المفروضة على الحلول المذكورة أعلاه، لذلك قمت بسرعة بتجميع برنامج في Go للقيام بهذه المهمة نيابةً عني.

يمكنك التحقق من الأداة هنا: فترة ما قبل الوقت

توجد ملفات تنفيذية تم إنشاؤها مسبقًا لنظام التشغيل Linux وMacOS وWindows في إطلاق قسم من مشروع جيثب.

تتعامل الأداة مع خطوط الإخراج غير المكتملة ولها (من وجهة نظري) بناء جملة أكثر إحكاما.

<command> | preftime

إنه ليس مثاليًا، لكنني على الرغم من أنني سأشاركه في حالة أنه يساعد شخصًا ما.

القيام بذلك مع date و tr و xargs على أو إس إكس:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate

إذا كنت تريد ميلي ثانية:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

لكن لاحظ أنه في OSX، لا يوفر لك التاريخ خيار %N، لذا ستحتاج إلى تثبيت gdate (brew install coreutils) وهكذا وصلنا أخيرًا إلى هذا:

alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

إذا كانت القيمة التي تعلقها مسبقًا هي نفسها في كل سطر، فقم بتشغيل emacs مع الملف، ثم:

كنترول + <مسافة>

في بداية الملف (لتحديد تلك النقطة)، ثم قم بالتمرير لأسفل إلى بداية السطر الأخير (Alt + > سينتقل إلى نهاية الملف...والتي من المحتمل أن تتضمن مفتاح Shift أيضًا، ثم Ctrl + a للانتقال إلى بداية هذا السطر) و:

كنترول + س ص ر

وهو الأمر الذي يجب إدراجه في المستطيل الذي حددته للتو (مستطيل بعرض 0).

21-8-2008 الساعة 6:45 مساءً <أدخل>

أو ما شئت أن تقدمه..ثم سترى هذا النص مُلحقًا بكل سطر داخل المستطيل ذي العرض 0.

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

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