Saya punya file dengan sekitar 1000 baris. Saya ingin bagian file saya setelah baris yang cocok dengan pernyataan grep saya.
Itu adalah:
$ cat file | grep 'TERMINATE' # It is found on line 534
Jadi, saya ingin file dari baris 535 ke baris 1000 untuk diproses lebih lanjut.
Bagaimana saya bisa melakukan itu?
grep 'TERMINATE' file
grep
antarmuka input standar untuk membaca data, daripada harus mempelajari saklar apa yang berlaku untukgrep
, dansed
, danawk
, danpandoc
, danffmpeg
lain - lain ketika kita ingin membaca dari file. Menghemat waktu karena kita tidak harus belajar peralihan baru setiap kali kita ingin melakukan hal yang sama: membaca dari file.grep 'TERMINATE' < file
. Mungkin itu memang membuat bacaan sedikit lebih sulit - tapi ini adalah shell scripting, jadi itu akan selalu menjadi masalah :)Jawaban:
Berikut ini akan mencetak baris yang cocok
TERMINATE
sampai akhir file:Dijelaskan:
-n
menonaktifkan perilaku defaultsed
pencetakan setiap baris setelah mengeksekusi skripnya di atasnya,-e
menunjukkan skrip untuksed
,/TERMINATE/,$
adalah pilihan kisaran alamat (baris) yang berarti baris pertama yang cocok denganTERMINATE
ekspresi reguler (seperti grep) ke akhir file ($
) , danp
merupakan perintah cetak yang mencetak baris saat ini.Ini akan mencetak dari baris yang mengikuti baris yang cocok
TERMINATE
sampai akhir file:(dari SETELAH baris yang cocok ke EOF, BUKAN termasuk baris yang cocok)
Dijelaskan:
1,/TERMINATE/
adalah pilihan rentang alamat (baris) yang berarti baris pertama untuk input ke baris 1 yang cocok denganTERMINATE
ekspresi reguler, dand
merupakan perintah hapus yang menghapus baris saat ini dan melompat ke baris berikutnya. Karenased
perilaku default adalah untuk mencetak garis, itu akan mencetak garis setelahTERMINATE
ke akhir input.Edit:
Jika Anda ingin garis sebelumnya
TERMINATE
:Dan jika Anda ingin kedua baris sebelum dan sesudah
TERMINATE
dalam 2 file berbeda dalam satu pass:File sebelum dan sesudah akan berisi baris dengan terminate, jadi untuk memproses setiap yang Anda butuhkan:
Sunting2:
JIKA Anda tidak ingin membuat kode nama file dalam skrip sed, Anda dapat:
Tapi kemudian Anda harus melarikan diri dari
$
makna baris terakhir sehingga shell tidak akan mencoba untuk memperluas$w
variabel (perhatikan bahwa kami sekarang menggunakan tanda kutip ganda di sekitar skrip alih-alih tanda kutip tunggal).Saya lupa mengatakan bahwa baris baru penting setelah nama file dalam skrip sehingga mereka tahu bahwa nama file berakhir.
Edit: 2016-0530
Sébastien Clément bertanya: "Bagaimana Anda mengganti hardcoded
TERMINATE
dengan variabel?"Anda akan membuat variabel untuk teks yang cocok dan kemudian melakukannya dengan cara yang sama seperti contoh sebelumnya:
untuk menggunakan variabel untuk teks yang cocok dengan contoh sebelumnya:
Poin penting tentang mengganti teks dengan variabel dalam kasus ini adalah:
$variablename
) yang disertakan dalamsingle quotes
['
] tidak akan "meluas" tetapi variabel di dalamdouble quotes
["
] akan. Jadi, Anda harus mengubah semuasingle quotes
untukdouble quotes
jika mereka mengandung teks yang ingin Anda ganti dengan variabel.sed
berkisar juga mengandung$
dan segera diikuti oleh surat seperti:$p
,$d
,$w
. Mereka juga akan terlihat seperti variabel yang akan diperluas, sehingga Anda harus melarikan diri mereka$
karakter dengan garis miring terbalik [\
] seperti:\$p
,\$d
,\$w
.sumber
sed -e "1,/$matchtext/d"
tidak berfungsi ketika$matchtext
muncul di baris pertama. Saya harus mengubahnya kesed -e "0,/$matchtext/d"
.Sebagai perkiraan sederhana yang dapat Anda gunakan
yang menangkap
TERMINATE
dan menghasilkan hingga 100000 baris mengikuti garis itu.Dari halaman manual
sumber
file
sebagai gantinya:grep -A$(cat file | wc -l) TERMINATE file
Alat yang digunakan di sini awk:
Bagaimana cara kerjanya:
Solusi lain mungkin menghabiskan banyak memori jika Anda menggunakannya pada file yang sangat besar.
sumber
cat file | awk 'BEGIN{ found=0} /###/{found=found+1} {if (found<2) print }'
cat
.awk
sangat mampu mengambil satu atau lebih nama file sebagai argumen. Lihat juga stackoverflow.com/questions/11710552/useless-use-of-catJika saya memahami pertanyaan Anda dengan benar Anda ingin garis setelah
TERMINATE
, tidak termasukTERMINATE
-line.awk
dapat melakukan ini dengan cara sederhana:Penjelasan:
if(found) print
) tidak akan mencetak apa pun untuk memulai.Ini akan mencetak semua baris setelah itu
TERMINATE
-line.Generalisasi:
Contoh:
Penjelasan:
found
diatur.found=1
sehingga baris-baris berikut dicetak. Perhatikan bahwa pemeriksaan ini dilakukan setelah pencetakan aktual untuk mengecualikan garis start dari hasilnya.Catatan:
BEGIN{found=0}
ke awal ekspresi awk.sumber
{if(found) print}
sedikit anti-pola dalam awk, itu lebih idiomatis untuk mengganti blok hanya denganfound
ataufound;
jika Anda memerlukan filter lain sesudahnya.awk '{if(found) print} /TERMINATE/{found=1}' your_file
denganawk 'found; /TERMINATE/{found=1}' your_file
, mereka berdua harus melakukan hal yang sama.Gunakan ekspansi parameter bash seperti berikut:
sumber
printf
atau memastikan Anda tahu persis apa yang Anda sampaikanecho
.).grep -Sebuah 10000000 'TERMINATE'
sumber
Ada banyak cara untuk melakukannya dengan
sed
atauawk
:Ini terlihat
TERMINATE
di file Anda dan dicetak dari baris itu hingga akhir file.Ini persis perilaku yang sama dengan
sed
.Jika Anda tahu jumlah baris dari mana Anda ingin mulai mencetak, Anda dapat menentukannya bersama
NR
(jumlah catatan, yang akhirnya menunjukkan jumlah baris):Contoh
sumber
more +7 file
Jika karena alasan apa pun, Anda ingin menghindari penggunaan sed, berikut ini akan mencetak baris yang cocok
TERMINATE
sampai akhir file:dan yang berikut ini akan dicetak dari baris berikut yang cocok
TERMINATE
sampai akhir file:Dibutuhkan 2 proses untuk melakukan apa yang dapat dilakukan sed dalam satu proses, dan jika file berubah antara eksekusi grep dan tail, hasilnya bisa membingungkan, jadi saya sarankan menggunakan sed. Selain itu, jika file yang dikerjakan tidak mengandung
TERMINATE
, perintah 1 gagal.sumber
Alternatif untuk
sed
jawaban yang sangat baik oleh jfgagne, dan yang tidak termasuk baris yang cocok:awk '/TERMINATE/ {y=1;next} y'
( https://stackoverflow.com/a/18166628 )awk '/TERMINATE/ ? c++ : c'
( https://stackoverflow.com/a/23984891 )perl -ne 'print unless 1 .. /TERMINATE/'
( https://stackoverflow.com/a/18167194 )sumber
Ini bisa menjadi salah satu cara untuk melakukannya. Jika Anda tahu baris file apa yang Anda miliki kata grep Anda dan berapa banyak baris yang Anda miliki di file Anda:
grep -A466 'TERMINATE' file
sumber
grep
tidak diperlukan; Anda bisa menggunakantail -n $NUM
, jadi ini bukan jawaban.sed adalah alat yang jauh lebih baik untuk pekerjaan itu: file sed -n '/ re /, $ p'
dimana re adalah regexp.
Pilihan lain adalah flag --after-context grep. Anda harus memasukkan angka untuk mengakhiri, menggunakan wc pada file harus memberikan nilai yang tepat untuk berhenti. Kombinasikan ini dengan -n dan ekspresi pertandingan Anda.
sumber
Ini akan mencetak semua baris dari baris terakhir yang ditemukan "TERMINATE" hingga akhir file:
sumber
grep
sehingga Anda dapat memberinya makantail
adalah antipattern yang boros. Menemukan kecocokan dan mencetak melalui akhir file (atau, sebaliknya, mencetak dan menghentikan pada kecocokan pertama) secara nyata dilakukan dengan alat regex yang normal dan esensial itu sendiri. Yang masifgrep | tail | sed | awk
juga dengan sendirinya merupakan penggunaangrep
dan teman yang tidak berguna .tail
dan lakukan tugas di alat yang lebih mampu sekaligus. Lagi pula, judulnya dengan jelas mengatakan "pertandingan pertama".