سؤال

هل هناك طريقة لتحديد ما إذا كان السطر الحالي هو السطر الأخير من دفق الإدخال؟

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

المحلول

لديك خياران، كلاهما نوع من الفوضى.

  1. قم بتخزين نسخة من كل سطر حالي في متغير مؤقت، ثم استخدم كتلة END لمعالجته.
  2. استخدم أمر النظام لتشغيل "wc -l | getline" في كتلة BEGIN للحصول على عدد الأسطر في الملف، ثم قم بعد تلك القيمة.

قد تضطر إلى اللعب بالرقم 2 قليلاً لتشغيله، لكنه يجب أن يعمل.لقد مر وقت طويل منذ أن فعلت أي شيء.

نصائح أخرى

ونمط END خاص وستكون مباراة إلا بعد نهاية <م> جميع المدخلات . لاحظ أن هذا النمط لا يمكن دمجها مع أي نمط آخر.

وأكثر فائدة وربما كان شبه وظيفة getline الذي يعيد تعيين $0 إلى السطر التالي والعودة 1، أو في حالة EOF عودة 0! وهو ما أعتقد أنه ما تريد.

وعلى سبيل المثال:

awk '{ if(getline == 0) { print "Found EOF"} }'

إذا كنت معالجة ملف واحد فقط، وهذا من شأنه أن يكون معادلا:

awk 'END { print "Found EOF" }'

وهذه هي الطرق الوحيد المعقول أن تفعل ما تريد، وذلك من الأفضل إلى الأسوأ:

awk 'NR==FNR{max++; next} FNR == max { print "Final line:",$0 }' file file

awk -v max="$(wc -l < file)" 'FNR == max { print "Final line:",$0 }' file

awk 'BEGIN{ while ( (getline dummy < ARGV[1]) > 0) max++; close(ARGV[1])} FNR == max { print "Final line:",$0 }' file

والكشف عن EOF ليست موثوقة جدا عندما ملفات متعددة هي على سطر الأوامر. الكشف عن بداية الملف هو أكثر موثوقية.

لذلك، الملف الأول هو خاص وتجاهلنا FNR == 1.

وبعد الملف الأول ثم FNR == 1 يصبح نهاية الملف السابق. last_filename دائما اسم الملف الذي كنت معالجة.

هل معالجة الملف بعد آخر.

هل معالجة EOF الخاص داخل كتلة آخر، وفي كتلة END.

   gawk 'BEGIN{last_filename="";} \
      FNR==1{if (last_filename==""){last_filename=FILENAME;} \
      else {print "EOF: "last_filename;last_filename=FILENAME;}} \
      END{print "END: "last_filename;}' $*

لمجموعات ملف متعددة، ينفذ كتلة آخر في EOF للجميع ولكن الملف الأخير. يتم تنفيذ الملف الأخير في كتلة END.

لمجموعات ملف واحد، وكتلة آخر لا يحصل تنفيذ، ويتم تنفيذ كتلة END.

أنا لست حتى متأكدا من كيفية تصنيف هذا "الحل"

{
    t = lastline
    lastline = $0
    $0 = t
}

/test/ {
    print "line <" $0 "> had a _test_"
}

END {
    # now you have "lastline", it can't be processed with the above statements
    # ...but you can work with it here
}

والشيء باردة حول هذا الإختراق هو أنه من خلال تكليف $0، جميع أنماط والإجراءات المعلن المتبقية العمل، سطر واحد تأخير. لا يمكنك الحصول عليها للعمل من أجل END، حتى لو كنت وضعت END على القمة، لكنك <م> لا السيطرة على السطر الأخير وأنت لم تفعل أي شيء آخر لذلك.

البله تنفيذ ديه قاعدة خاصة تسمى ENDFILE التي سيتم تشغيلها بعد معالجة كل ملف في قائمة وسيطة . يعمل هذا:

awk '{line=$0} ENDFILE {print line}' files...

ومزيد من التفاصيل يمكنك العثور هنا >>

واحد طريقة سهلة لتشغيل الملف عبر برنامج نصي sed وسيطة، أن يضع 0 على كل غير السطر الأخير، و1 على آخر.

cat input_file | sed 's/^/0/;$s/0/1/' | awk '{LST=/^1/;$0=substr($0,2)}
... your awk script in which you can use LST to check for the
... last line.'

لكشف السطر الأخير من كل ملف في قائمة وسيطة الأعمال التالية لطيف:

FNR == 1 || EOF {
  print "last line (" FILENAME "): " $0
}

وهم المتغير AWK END يقول عندما كنت قد وصلت بالفعل EOF. ليس حقا الكثير من المساعدة لك أعتقد

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

awk 'BEGIN{PFNR=1} FNR==PFNR{PFNR++;next} {print FILENAME,PFNR=2} END{print FILENAME}' file1 file2

يتم توفير حل محمول في البله دليل المستخدم ، على الرغم كما ورد في إجابة أخرى، البله نفسها لديها BEGINFILE وENDFILE.

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