it-swarm.asia

أمر سريع يونيكس لعرض خطوط محددة في منتصف الملف؟

محاولة تصحيح مشكلة في الخادم وملف السجل الوحيد الخاص بي هو ملف سجل بسعة 20 جيجابايت (مع عدم وجود طوابع زمنية حتى! لماذا يستخدم الناس System.out.println() كالتسجيل؟ في الإنتاج؟!)

باستخدام grep ، وجدت مساحة من الملف أرغب في إلقاء نظرة عليها ، السطر 347340107.

بخلاف فعل شيء مثل

head -<$LINENUM + 10> filename | tail -20 

... والتي تتطلب head قراءة خلال أول 347 مليون سطر من ملف السجل ، هل هناك أمر سريع وسهل من شأنه تفريغ الأسطر 347340100 - 347340200 (على سبيل المثال) إلى وحدة التحكم؟

update لقد نسيت تمامًا أن grep يمكنه طباعة السياق حول المطابقة ... هذا يعمل بشكل جيد. شكر!

175
matt b

مع GNU-grep يمكنك القول فقط

grep --context = 10 ...
68
Mathias Weidner

لقد وجدت حلين آخرين حلول إذا كنت تعرف رقم السطر ولكن لا يوجد شيء آخر (لا يوجد grep ممكن):

على افتراض أنك بحاجة إلى خطوط 20 إلى 40 ،

sed -n '20,40p;41q' file_name

أو

awk 'FNR>=20 && FNR<=40' file_name
353
Sklivvz
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

الطريقة الثالثة فعالة في الملفات الكبيرة

أسرع طريقة لعرض خطوط محددة

101
WCC

لا ، ليس هناك ملفات غير قابلة للخط.

لا توجد طريقة وقت ثابت للعثور على بداية السطر n في ملف نصي. يجب عليك دفق الملف وحساب الأسطر الجديدة.

استخدم أبسط/أسرع أداة لديك للقيام بهذه المهمة. بالنسبة لي ، استخدام head يجعل كثيرًا أكثر منطقية من grep ، لأن الأخير أكثر تعقيدًا. أنا لا أقول "grep بطيء" ، إنه ليس كذلك بالفعل ، لكنني سأشعر بالدهشة إذا كان أسرع من head لهذه الحالة. سيكون ذلك خطأ في head ، بشكل أساسي.

23
unwind

ماذا عن:

tail -n +347340107 filename | head -n 100

لم أختبرها ، لكنني أعتقد أن ذلك سينجح.

19
itsmatt

سأقوم أولاً بتقسيم الملف إلى عدد أصغر من هذا القبيل

$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix

ثم grep على الملفات الناتجة.

12
Luka Marinko

انا افضل الذهاب الى less و

  • الكتابة 5% للانتقال إلى منتصف الملف ،
  • 43210G للذهاب إلى خط 43210
  • :43210 لفعل الشيء نفسه

وأشياء من هذا القبيل.

حتى أفضل: ضرب v لبدء التحرير (في vim ، بالطبع!) ، في هذا الموقع. الآن ، لاحظ أن vim لديه روابط المفاتيح نفسها!

11
sehe

يمكنك استخدام ex الأمر ، محرر Unix قياسي (جزء من Vim الآن) ، على سبيل المثال.

  • عرض سطر واحد (مثل الخط الثاني):

    ex +2p -scq file.txt
    

    بناء الجملة المقابلة: sed -n '2p' file.txt

  • نطاق الخطوط (مثل 2-5 خطوط):

    ex +2,5p -scq file.txt
    

    بناء جملة sed: sed -n '2,5p' file.txt

  • من السطر المحدد حتى النهاية (على سبيل المثال ، من 5 إلى نهاية الملف):

    ex +5,p -scq file.txt
    

    بناء جملة sed: sed -n '2,$p' file.txt

  • نطاقات الأسطر المتعددة (مثل 2-4 و 6-8 خطوط):

    ex +2,4p +6,8p -scq file.txt
    

    بناء جملة sed: sed -n '2,4p;6,8p' file.txt

يمكن اختبار الأوامر أعلاه باستخدام ملف الاختبار التالي:

seq 1 20 > file.txt

تفسير:

  • + أو -c متبوعًا بالأمر - قم بتنفيذ الأمر (vi/vim) بعد قراءة الملف ،
  • -s - الوضع الصامت ، ويستخدم أيضًا المحطة الحالية كإخراج افتراضي ،
  • q متبوعًا بـ -c هو أمر إنهاء المحرر (إضافة ! للقيام بفرض الإقلاع ، على سبيل المثال -scq!).
8
kenorb

الحصول على ack

ack - خطوط = اسم ملف البدء

5
Odeyin

ستحتاج sed إلى قراءة البيانات أيضًا لحساب الخطوط. الطريقة الوحيدة الممكنة للاختصار هي وجود سياق/ترتيب في الملف للعمل عليه. على سبيل المثال ، إذا كان هناك خطوط سجل معدة مسبقًا بوقت/تاريخ عرض ثابت وما إلى ذلك ، يمكنك استخدام الأداة المساعدة look unix للبحث الثنائي من خلال الملفات لتواريخ/أوقات محددة

4
pixelbeat

استعمال

x=`cat -n <file> | grep <match> | awk '{print $1}'`

هنا سوف تحصل على رقم السطر الذي حدثت فيه المباراة.

يمكنك الآن استخدام الأمر التالي لطباعة 100 سطر

awk -v var="$x" 'NR>=var && NR<=var+100{print}' <file>

أو يمكنك استخدام "sed" كذلك

sed -n "${x},${x+100}p" <file>
3
Ramana Reddy

إذا كان رقم السطر هو 100 لقراءة

head -100 filename | tail -1
3
Roopa

بناءً على إجابة Sklivvz ، إليك وظيفة لطيفة يمكن للمرء وضعها في ملف .bash_aliases. إنه فعال في الملفات الضخمة عند طباعة الأشياء من مقدمة الملف.

function middle()
{
    startidx=$1
    len=$2
    endidx=$(($startidx+$len))
    filename=$3

    awk "FNR>=${startidx} && FNR<=${endidx} { print NR\" \"\$0 }; FNR>${endidx} { print \"END HERE\"; exit }" $filename
}
2
Keithel

مع sed -e '1,N d; M q' ، ستقوم بطباعة الخطوط من N + 1 إلى M. وقد يكون هذا أفضل قليلاً ثم grep -C لأنه لا يحاول مطابقة الخطوط بنمط معين.

2
mweerden

لعرض سطر من <textfile> بواسطة <line#> الخاص به ، ما عليك سوى القيام بذلك:

Perl -wne 'print if $. == <line#>' <textfile>

إذا كنت تريد طريقة أكثر قوة لإظهار مجموعة من الخطوط مع التعبيرات العادية - لن أقول لماذا تعتبر grep فكرة سيئة للقيام بذلك ، يجب أن تكون واضحة إلى حد ما - هذا التعبير البسيط سيوضح لك النطاق الخاص بك في تمرير واحد وهو ما تريده عند التعامل مع الملفات النصية ~ 20GB:

Perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename>

(نصيحة: إذا كان لديك regex / فيه ، فاستخدم شيئًا مثل m!<regex>! بدلاً من ذلك)

سيؤدي ذلك إلى طباعة <filename> بدءًا من السطر الذي يطابق <regex1> حتى (ويشمل ذلك) السطر الذي يطابق <regex2>.

لا يتطلب الأمر معالجًا لمعرفة كيفية قيام بعض الأقراص بتعديله.

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

1
osirisgothra

سهل مع بيرل! إذا كنت ترغب في الحصول على السطر 1 و 3 و 5 من الملف ، قل/etc/passwd:

Perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
0
dagelf

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

egrep -n "*" <filename> | egrep "<line number>"
0
Fritz Dodoo

أنا مندهش فقط إجابة واحدة أخرى (بواسطة رامانا ريدي) اقترح إضافة أرقام الأسطر إلى الإخراج. يبحث التالي عن رقم السطر المطلوب ولون الإخراج.

file=FILE
lineno=LINENO
wb="107"; bf="30;1"; rb="101"; yb="103"
cat -n ${file} | { GREP_COLORS="se=${wb};${bf}:cx=${wb};${bf}:ms=${rb};${bf}:sl=${yb};${bf}" grep --color -C 10 "^[[:space:]]\\+${lineno}[[:space:]]"; }
0
eel ghEEz