Sed - ganti karakter dalam garis yang cocok di tempatnya?

21

Dalam file yang berisi baris seperti ini:

# lorem ipsum blah variable

Saya ingin menghapus #(komentar) karakter di baris yang sama yang berisi string tertentu, di tempat. Apakah sedbaik untuk ini?

Saya berjuang agar kondisional ini berfungsi. Saya memiliki cara "canggung" untuk melakukan ini; Saya dapat menemukan nomor baris yang cocok dengan awkatau seddan kemudian menggunakan nomor ini dalam sedperintah terpisah , tetapi saya percaya bahwa ini dapat dilakukan dengan cara yang jauh lebih baik.

Kamil
sumber

Jawaban:

36

Gunakan string yang Anda cari sebagai pemilih untuk jalur yang akan dioperasikan:

sed '/ipsum/s/#//g'

/ipsum/memilih baris yang mengandung "ipsum" dan hanya pada baris ini perintah yang dijalankan dijalankan. Anda dapat menggunakan kawat gigi untuk menjalankan lebih banyak perintah

/ipsum/{s/#//g;s/@/-at-/g;}
peterph
sumber
4
Saya setuju; ini adalah jawaban terbaik (walaupun bukan satu-satunya). Komentar: (1) 's/#//g'akan menghapus semua yang #karakter di baris. Jika bukan itu yang Anda inginkan, hapus g(yang merupakan singkatan dari "global"). (2) Untuk mengedit file di tempat (seperti yang diminta dalam pertanyaan), gunakan sed -i.
G-Man Mengatakan 'Reinstate Monica'
2
(3) Sehubungan dengan situasi dunia nyata, jika Anda ingin berhenti mengomentari suatu baris, Anda mungkin ingin menggunakan sed -i '/ipsum/s/#[[:space:]]*//', untuk menghilangkan spasi dan tab segera setelah #. (4) Anda mungkin juga ingin mempertimbangkan untuk memverifikasi bahwa itu #adalah karakter non-kosong pertama dalam baris. Perintah saat ini akan menghapus #dari baris prompt "Enter # of ipsums:".
G-Man Mengatakan 'Reinstate Monica'
1
@ G-Man - tambahan yang bagus! Untuk pt 2 Anda (ruang terdepan), bagaimana dengan: sed -i '/ipsum/s/^#[[:space:]]*//'?! ( ^menandakan mulai dari garis, $untuk akhir baris) - setidaknya dalam gnu sed ...
Jeremy Davis
1
@JeremyDavis: Ya, Anda bisa menempelkan regex ke awal baris ^, tapi itu salah. Saya sering mengomentari kode indentasi dengan meletakkan #kode sebelum kode, jadi #indentasi. Saya ragu bahwa saya satu-satunya orang yang melakukan itu.
G-Man Mengatakan 'Reinstate Monica'
1
@ G-Man - ah ya, tentu saja! Terima kasih, saya tidak mempertimbangkan itu. Sehingga Anda juga akan ingin memeriksa spasi antara ^& #, jadi sesuatu yang lebih seperti ini: /ipsum/{/^[[:space:]]*#/s/#[[:space:]]*//}. Meskipun demikian, tergantung di mana tempatnya #, masih dapat menyebabkan masalah (misalnya dalam bahasa yang menggunakan lekukan / pemisahan spasi).
Jeremy Davis
7
$ cat input.txt
# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
# lorem ipsum blue variable

kemudian:

$ sed 's|# \(.*blue.*\)|\1|' input.txt

memberi:

# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
lorem ipsum blue variable

Ia bekerja sebagai berikut:

The smengatakan sedbahwa itu harus mengganti apa ekspresi reguler menemukan.

Pola # \(.*blue.*\)yang memecah menjadi: Temukan hash diikuti oleh spasi. Braket ( \() memulai pengelompokan. .*blue.*adalah kata bluedengan apa pun sebelum dan sesudah. Braket berikutnya ( \)) menutup pengelompokan.

Penggantian tersebut \1adalah referensi balik ke konten braket pengelompokan pertama.

garethTheRed
sumber
3

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc '/ipsum/s/#//|x' file
  1. s pengganti

  2. x Simpan dan tutup

Steven Penny
sumber
Itu keren sekali. Saya tidak tahu tentang itu! TBH, saya tidak yakin itu jawaban terbaik untuk pertanyaan ini (IMO, jawaban sed yang paling utama), tetapi masih sangat keren! Terima kasih telah memposting.
Jeremy Davis