it-swarm.dev

الطباعة مع sed أو awk خط يتبع نمط مطابقة

السؤال: أرغب في طباعة سطر واحد يتبع خطًا يحتوي على نقش مطابق.

لن يأخذ إصدار sed بناء الجملة التالي (إنه يفجر في +1p) التي تبدو وكأنها حل بسيط:

sed -n '/ABC/,+1p' infile

أفترض awk سيكون من الأفضل إجراء معالجة متعددة الأسطر ، لكنني لست متأكدًا من كيفية القيام بذلك.

52
user1537723

لا تستخدم كلمة "النقش" أبدًا كما هي غامضة للغاية. استخدم دائمًا "string" أو "regexp" (أو في Shell "globbing pattern") ، أيهما تقصد حقًا.

الإجابة المحددة التي تريدها هي:

awk 'f{print;f=0} /regexp/{f=1}' file

أو التخصص في الحل الأكثر عمومية من السجل Nth بعد regexp (المصطلح "c" أدناه):

awk 'c&&!--c; /regexp/{c=1}' file

تصف العبارات الاصطلاحية التالية كيفية تحديد مجموعة من السجلات التي تعطى إعادة رجوع محددة لمطابقتها:

أ) طباعة جميع السجلات من بعض regexp:

awk '/regexp/{f=1}f' file

ب) اطبع جميع السجلات بعد بعض إعادة التسجيل:

awk 'f;/regexp/{f=1}' file

ج) اطبع السجل Nth بعد بعض إعادة الاسترداد:

awk 'c&&!--c;/regexp/{c=N}' file

د) طباعة كل سجل باستثناء السجل Nth بعد بعض إعادة الاسترداد:

awk 'c&&!--c{next}/regexp/{c=N}1' file

ه) طباعة السجلات N بعد بعض regexp:

awk 'c&&c--;/regexp/{c=N}' file

و) قم بطباعة كل سجل باستثناء السجلات N بعد إعادة تسجيل:

awk 'c&&c--{next}/regexp/{c=N}1' file

ز) اطبع سجلات N من بعض إعادة الحساب:

awk '/regexp/{c=N}c&&c--' file

لقد غيرت اسم المتغير من "f" لـ "found" إلى "c" لـ "count" كلما كان ذلك مناسبًا لأنه أكثر تعبيرًا عن المتغير بالفعل.

121
Ed Morton

إنه السطر بعد الذي يطابق اهتمامك ، أليس كذلك؟ في sed ، يمكن تحقيق ذلك مثل:

sed -n '/ABC/{n;p}' infile

بدلاً من ذلك ، grep's A قد يكون الخيار هو ما تبحث عنه.

-A NUM, Print NUM lines of trailing context after matching lines.

على سبيل المثال ، بالنظر إلى ملف الإدخال التالي:

foo
bar
baz
bash
bongo

يمكنك استخدام ما يلي:

$ grep -A 1 "bar" file
bar
baz
$ sed -n '/bar/{n;p}' file
baz

امل ان يساعد.

37
chooban

كنت بحاجة لطباعة جميع الخطوط بعد النقش (حسناً Ed ، REGEX) ، لذلك استقرت على هذا:

sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern

ولكن منذ أن أردت طباعة جميع الخطوط بعد (واستبعاد النمط)

sed -n '/pattern/,$p' | tail -n+2  # all lines after first occurrence of pattern

أفترض في قضيتك أنه يمكنك إضافة head -1 في نهايةالمطاف

sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
5
Mark

الإصدار awk:

awk '/regexp/ { getline; print $0; }' filetosearch
2
tue

هذا قد يصلح لك (GNU sed):

sed -n ':a;/regexp/{n;h;p;x;ba}' file

استخدم خيار seds-like like -n وإذا كان السطر الحالي يحتوي على إعادة الاسترداد المطلوبة ، فاستبدل السطر الحالي بالسطر التالي ، وانسخ هذا السطر إلى مساحة التعليق (HS) ، وطبع السطر ، وقم بمبادلة مساحة النمط (PS) لنظام HS وكرر.

1
potong

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

sed '/pattern/ { N; s/.*\n//; q }; d'
1
Michael Back

في الواقع sed -n '/pattern/{n;p}' filename ستفشل إذا كانت الأسطر pattern تطابق continuous:

$ seq 15 |sed -n '/1/{n;p}'
2
11
13
15

الإجابات المتوقعة يجب أن تكون:

2
11
12
13
14
15

الحل الخاص بي هو:

$ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename

فمثلا:

$ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
2
11
12
13
14
15

ويوضح:

  1. x;: في بداية كل سطر من الإدخال ، استخدم x الأمر لتبادل المحتويات في pattern space & hold space.
  2. /_/{x;p;x};: إذا pattern space ، وهو hold space فعليًا ، يحتوي على _ (هذا فقط indicator يشير إلى ما إذا كان السطر الأخير مطابقًا لـ pattern أو لا) ، ثم استخدم x لتبادل المحتوى الفعلي لـ current line إلى pattern space ، استخدم p لطباعة current line و x لاستعادة هذه العملية.
  3. x: استرداد المحتويات في pattern space و hold space.
  4. /pattern/!s/.*//: إذا لم يتطابق current linepattern ، مما يعني أنه لا ينبغي لنا طباعة السطر التالي ، فاستخدم الأمر s/.*// لحذف جميع المحتويات في pattern space.
  5. /pattern/s/.*/_/: إذا تطابقت current linepattern ، مما يعني أنه يجب علينا طباعة السطر التالي ، فسنحتاج إلى تعيين indicator لإخبار sed لطباعة سطر NEXT ، لذا استخدم s/.*/_/ لاستبدال جميع المحتويات في pattern space بـ _ (سيستخدم الأمر الثاني للحكم إذا تطابق السطر الأخير مع pattern أم لا).
  6. h: الكتابة فوق hold space بالمحتويات الموجودة في pattern space ؛ ثم ، المحتوى الموجود في hold space هو ^_$ مما يعني current line يطابق pattern ، أو ^$ ، مما يعني current line ] لا يطابق pattern.
  7. لا يمكن استبدال الخطوة الخامسة والخطوة السادسة ، لأنه بعد s/.*/_/ ، لا يمكن أن يتطابق pattern space/pattern/ ، لذا يجب تنفيذ s/.*//!
1
Weike