كيف يمكنني إنشاء أمر VIM أو VI لحذف جميع النصوص بعد حرف معين لكل سطر في ملف نصي؟
سؤال
سيناريو:
- لدي ملف نصي يحتوي على أنبوب (كما في
|
الشخصية) البيانات المحددة. - يمكن أن يكون كل حقل من البيانات في الحقول المحددة للأنابيب ذات طول متغير ، لذلك لن يعمل حساب الأحرف (أو باستخدام نوع من الوظائف الفرعية ... إذا كان ذلك موجودًا في VIM).
هل من الممكن ، باستخدام VIM / VI لحذف جميع البيانات من الأنبوب الثاني إلى نهاية السطر للملف بأكمله؟ هناك حوالي 150،000 سطر ، لذا فإن القيام بذلك يدويًا لن يكون جذابًا لماسوشي ...
على سبيل المثال
قم بتغيير الأسطر التالية من:
1111|random sized text 12345|more random data la la la|1111|abcde
2222|random sized text abcdefghijk|la la la la|2222|defgh
3333|random sized text|more random data|33333|ijklmnop
إلى:
1111|random sized text 12345
2222|random sized text abcdefghijk
3333|random sized text
أنا متأكد من أنه يمكن القيام بذلك بطريقة أو بأخرى ... آمل.
تيا
تحديث: كان يجب أن أذكر أنني أقوم بتشغيل هذا على Windows XP ، لذلك لا يمكنني الوصول إلى بعض أوامر *NIX المذكورة (لم يتم التعرف على القطع على Windows).
المحلول
:%s/^\v([^|]+\|[^|]+)\|.*$/\1/
نصائح أخرى
يمكنك أيضًا تسجيل ماكرو:
qq02f|Djq
وبعد ذلك ستتمكن من تشغيله مع 100@Q لتشغيل الماكرو على السطر المائة التالي.
تفسير الماكرو:
- QQ - يبدأ تسجيل الماكرو
- 0 - انتقل إلى الطابع الأول للخط
- 2F | - العثور على الحدوث الثاني من | شخصية على الخط
- د - احذف النص بعد الموضع الحالي إلى نهاية الخط
- ي - انتقل إلى السطر التالي
- س - ينتهي تسجيل الماكرو
إذا لم يكن عليك استخدام VIM ، فإن بديل آخر هو أمر UNIX "CUT".
cut -d '|' -f 1-2 file > out.file
مجرد طريقة أخرى لفعل الشيء نفسه:
%s/^\(.\{-}|\)\{2}\zs.*//
%s/^\(.\{-}\zs|\)\{2}.*// " if you want to remove the 2nd pipe as well
هذه المرة ، تتطابق regex مع عدد قليل من الأحرف ( {-}) قدر الإمكان والتي تليها أنبوب ، ومرتين ( {2}) ، يتم تجاهلها (zS) لاستبدال كل ما يلي ( Zس) نص لا شيء.
بدلاً من الاستبدال يمكن للمرء استخدام :normal
أمر بتكرار تسلسل من اثنين من أوامر الوضع العادي القفز إلى الثانية |
الشخصية وحذف كل شيء آخر حتى نهاية الخط.
:%norm!2f|D
استخدام: أمر لإنشاء أمر مستخدم يمكنك تشغيله بسهولة.
:command -range=% YourNameHere <line1>,<line2>s/^\v([^|]+\|[^|]+)\|.*$/\1/
يمكنك أيضًا القيام بذلك:
:%s/^\([^\|]\+|[^\|]\+\)\|.*$/\1/g
استخدم awk.
awk -F"|" '{$0=$1"|"$2}1' file
لقد وجدت أن VIM ليس رائعًا في التعامل مع الملفات الكبيرة جدًا. لست متأكدًا من حجم ملفك. ربما تعمل Cat و Sed معًا بشكل أفضل.
هنا حل SED:
sed -e 's/^\([^|]*|[^|]*\).*$/\1/'
سيؤدي ذلك إلى تصفية جميع الخطوط في المخزن المؤقت (1 ، $) من خلال القطع للقيام بالمهمة.
:1,$!cut -d '|' -f 1-2
محاولة مع
:.!cut -d '|' -f 1-2
للقيام بذلك فقط على الخط الحالي.
لماذا تستخدم VIM؟
لماذا لا تفعل فقط
cat my_pipe_file | cut -d'|' -f1-2