Apakah skenario ekstraksi teks ini dimungkinkan di linux bash Shell?

Katakanlah file teks saya seperti ini

Orang1 : film1
(spasi dan tab): film 2
(spasi dan tab): film 3
(spasi dan tab): film 4

Saya ingin mencari film tertentu, aktornya. Jadi, inilah cara saya melakukan ini.

Lakukan aktor kucing grep | ambil 'film3'

Ini akan memberi saya baris 3 yang merupakan baris kosong sampai film3 muncul. Jadi entah bagaimana saya bisa mendapatkan baris pertama sebelum baris khusus ini yang mengikuti pola ini

grep '^[^ \t].'(tidak diawali dengan spasi)

harus sesuai dengan nama aktor di film ini. (Saya tidak peduli dengan film yang ada di sana)

Apakah ada kombinasi sed/grep/awk yang dapat membantu saya melakukannya di Shell? Saya harap pertanyaannya jelas.


person Dude    schedule 29.06.2014    source sumber


Jawaban (4)


Bill Murray ‹- Groundhog Day ‹- terima dengan mode Perl Magic

Ini agak rumit, tetapi Anda bisa menggunakan ini:

grep -P "(?sm)^\S+[^:\r\n]*?(?=\s*:(?:(?!^\S).)*?Groundhog Day)" mymoviefile

Lihat demo.

  • -P mengaktifkan mode Perl
  • (?sm) mengaktifkan dua pengubah mode:
  • s mengaktifkan mode DOTALL, memungkinkan titik cocok dengan garis
  • m mengaktifkan mode multi-baris, memungkinkan ^ dan $ untuk mencocokkan pada setiap baris
  • Jangkar ^ menegaskan bahwa kita berada di awal baris
  • \S+ cocok dengan satu atau lebih karakter non-spasi
  • [^:\r\n]*? dengan malas mencocokkan karakter non-titik dua, non-baris baru, hingga ...
  • titik di mana pandangan ke depan (?=\s*:(?:(?!^\S).)*?Groundhog Day) dapat menegaskan, tanpa menggunakan karakter, bahwa berikut ini adalah...
  • \s*: spasi opsional dan titik dua
  • lalu (?:(?!^\S).)* nol atau lebih karakter yang bukan karakter non-spasi di awal baris, dengan malas mencocokkan hingga...
  • Groundhog Day judul filmnya!

Referensi

person zx81    schedule 29.06.2014
comment
Saya mencoba menjalankannya. Tidak bekerja. Ini pesan kesalahannya grep: karakter tidak dikenal setelah (? atau (?-. Saya mencoba men-debugnya, tetapi karena ini sangat rumit, dan saya tidak tahu setengah dari hal-hal yang telah Anda gunakan di sini, saya rasa saya akan melakukannya membutuhkan bantuan Anda lebih lanjut. :^D - person Dude; 29.06.2014
comment
Menambahkan tweak dan tweak, lihatlah. :) - person zx81; 29.06.2014
comment
Terima kasih atas bantuan Anda. Tapi ini jelas bukan untuk mereka yang lemah hati. - person Dude; 29.06.2014
comment
Selesai penjelasannya. ` ini jelas bukan untuk orang yang lemah hati` Anda benar, ini jauh dari jelas, tapi dengan penjelasannya saya yakin Anda akan bisa memahaminya. Apakah ini berhasil? - person zx81; 29.06.2014
comment
Terima kasih Bung, senang ini membantu! :) - person zx81; 29.06.2014
comment
Setelah penjelasan itu, saya sebenarnya berutang setidaknya 50-60 reputasi kepada Anda! :) - person Dude; 29.06.2014
comment
Nah, sungguh menyenangkan, sama-sama! :) Jika Anda ingin membantu saya (atau Anda), pelajari beberapa regex keren lainnya! :) Misalnya ada beberapa pertanyaan menarik di panel kanan profil saya, FAQ regex juga bagus, kemudian dijawab oleh beberapa dewa regex di sini (klik pengguna teratas sepanjang masa di tag regex), atau situs seperti regular-expressions.info dan rexegg... Regex keren, Bung! :) - person zx81; 29.06.2014

Saya akan melakukannya dengan awk jika saya tidak memahami masalahnya dengan benar:

 awk -F: -v s="$search" '$1~/\S/{p=$1}$2~s{print $1 FS $2}' file

uji dengan movie 3:

kent$ cat f
Person1 : movie1
          : movie 2
          : movie 3
          : movie 4

pada file di atas, ada spasi/tab di depannya

kent$  awk -F: -v s="movie 3" '$1~/\S/{p=$1}$2~s{print p FS $2}' f
Person1 : movie 3
person Kent    schedule 29.06.2014
comment
Saya membuat file seperti milik Anda, tanpa spasi di depan baris dengan person1: movie1. dan saya menjalankan perintah persis seperti yang Anda berikan kepada saya. Itu hanya memberikan ini, (awal baris): film 3. - person Dude; 29.06.2014
comment
Saya menggunakan Linux. Diharapkan berfungsi di sana, jika Anda menjalankannya di Mac? - person Dude; 29.06.2014
comment
@Bung, saya hanya punya linux. Saya rasa karena versi gawk Anda lebih rendah dari versi saya, Anda dapat mencoba: awk ... '$1~/[^ \t]/{....}' - person Kent; 29.06.2014
comment
Ya, itu berhasil. Jika Anda tidak keberatan, bisakah Anda menjelaskan regex secara singkat. - person Dude; 29.06.2014
comment
@Bung, regex hanya cocok dengan string ($1, kolom pertama) jika berisi karakter yang tidak kosong. Masalah seperti itu biasa terjadi pada awk. grep memang bagus, tapi ini bukan alat yang tepat untuk itu. (pendapat saya) - person Kent; 29.06.2014

Ini mungkin berhasil untuk Anda (GNU sed):

sed -n '/^\S/h;/movie 3/{H;x;s/:.*:/:/p}' file

Gunakan sakelar -n untuk memberikan sifat seperti grep. Simpan orang tersebut di ruang tunggu dan tambahkan film ke dalamnya. Kemudian hapus teks yang tidak diinginkan dan cetak.

person potong    schedule 29.06.2014

Ini agak tidak jelas tetapi selesaikan pekerjaannya:

awk '/^[^ ]/{p=0} /Person1/{p=1} p'

Contoh:

Berkas masukan:

Person1 : movie1
    : movie 2
    : movie 3
    : movie 4
Person2 : movie 5
    : movie 6

Eksekusi:

awk '/^[^ ]/{p=0} /Person1/{p=1} p' file
Person1 : movie1
    : movie 2
    : movie 3
    : movie 4

awk '/^[^ ]/{p=0} /Person2/{p=1} p' file
Person2 : movie 5
    : movie 6

OBS: Pada baris perintah, outputnya diindentasi.

Penjelasan:

  1. Jika garis tidak dimulai dengan spasi, himpunan p=0
  2. Jika baris berisi Person1 set p=1
  3. jika p=1 maka cetak (Bagian ini tidak jelas)

Dapat dilakukan di perl juga:

perl -ne '/^\w+/ && {$p=0}; /Person1/ && {$p=1}; $p && {print}' 
person Tiago Lopo    schedule 29.06.2014