Untuk beberapa alasan saya sepertinya tidak dapat menemukan jawaban langsung untuk ini dan saya sedang sedikit kesal saat ini. Bagaimana cara saya memasukkan baris teks pilihan setelah baris pertama yang cocok dengan string tertentu menggunakan sed
perintah. Saya sudah ...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
Dan saya ingin memasukkan garis setelah CLIENTSCRIPT=
garis yang menghasilkan ...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
sed
. Itu bukansed
sintaks standar dan tidak akan berfungsi dengansed
implementasi lainnya .Perhatikan standarnya
sed
sintaks (seperti pada POSIX, yang didukung oleh semuased
implementasi yang sesuai di sekitar (GNU, OS / X, BSD, Solaris ...)):Atau di satu baris:
(
-e
xpressions (dan konten-f
iles) digabungkan dengan baris baru untuk membuatsed
interpretasi skrip sed ).The
-i
pilihan untuk mengedit di tempat juga merupakan ekstensi GNU, beberapa implementasi lainnya (seperti FreeBSD) dukungan-i ''
untuk itu.Atau, untuk portabilitas, Anda dapat menggunakan
perl
:Atau Anda bisa menggunakan
ed
atauex
:sumber
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
lolos dari kutipan di akhir parameter pertama dan melanggar perintah.csh
ataurc
keluarga,'...'
adalah kutipan kuat di mana backslash tidak istimewa. Satu-satunya pengecualian yang saya tahu adalahfish
shell.sed
tidak sesuai dengan POSIX di sini. Itu membuat pernyataan saya tentang itu menjadi portable salah (untuk varian satu baris). Saya akan meminta konfirmasi kepada grup pembuka apakah ini benar-benar ketidaksesuaian atau salah tafsir standar.Yang kompatibel dengan POSIX menggunakan
s
perintah:sumber
sed -e '/.../s/$/\' -e 'CLI.../'
yang akan menghindari masalah dengan baris yang mengandung urutan byte yang tidak membentuk karakter yang valid.Perintah sed yang bekerja pada MacOS (setidaknya, OS 10) dan Unix sama (mis. Tidak memerlukan gnu sed seperti Gilles '(saat ini diterima) seseorang melakukannya):
Ini berfungsi dalam bash dan mungkin juga shells lain yang mengetahui gaya kutipan evaluasi $ '\ n'. Semuanya bisa dalam satu baris dan bekerja di perintah sed / POSIX yang lebih lama. Jika mungkin ada beberapa baris yang cocok dengan CLIENTSCRIPT = "foo" (atau yang setara dengan Anda) dan Anda hanya ingin menambahkan baris tambahan pertama kali, Anda dapat mengolahnya kembali sebagai berikut:
(ini membuat loop setelah kode penyisipan baris yang hanya menggilir sisa file, tidak pernah kembali ke perintah sed pertama lagi).
Anda mungkin memperhatikan bahwa saya menambahkan '^ *' ke pola yang cocok kalau-kalau baris tersebut muncul dalam komentar, katakanlah, atau indentasi. Ini tidak 100% sempurna tetapi mencakup beberapa situasi lain yang cenderung umum. Sesuaikan sesuai kebutuhan ...
Kedua solusi ini juga menyelesaikan masalah (untuk solusi umum untuk menambahkan baris) bahwa jika baris baru Anda yang dimasukkan berisi garis miring terbalik atau ampersand mereka akan ditafsirkan dengan sed dan kemungkinan tidak akan keluar sama, seperti halnya
\n
- misalnya.\0
akan menjadi baris pertama yang cocok. Sangat berguna jika Anda menambahkan baris yang berasal dari variabel di mana Anda harus melarikan diri semuanya terlebih dahulu menggunakan $ {var //} sebelumnya, atau pernyataan lain dll.Solusi ini sedikit kurang berantakan dalam skrip (yang mengutip dan \ n tidak mudah dibaca), ketika Anda tidak ingin meletakkan teks pengganti untuk perintah di awal baris jika mengatakan, dalam suatu fungsi dengan garis lekuk. Saya telah mengambil keuntungan bahwa $ '\ n' dievaluasi ke baris baru oleh shell, ini bukan dalam nilai kutip tunggal '\ n' biasa.
Sudah cukup lama saya pikir perl / awk mungkin menang karena lebih mudah dibaca.
sumber
s/CLIENTSCRIPT="foo"/&\
[Enter]CLIENTSCRIPT2="hello"/
. Garis miring terbalik harus menjadi karakter terakhir di baris (tidak ada spasi setelahnya), bertentangan dengan tampilannya di komentar ini.s///
, serta yang ada dia
dani
perintah dapat "melarikan diri," menggunakan metode yang sama yang saya jelaskan dalam komentar saya di atas.Mungkin agak terlambat untuk mengirim jawaban untuk ini, tetapi saya menemukan beberapa solusi di atas agak rumit.
Saya mencoba penggantian string sederhana di sed dan berhasil:
& tanda mencerminkan string yang cocok, lalu Anda menambahkan \ n dan baris baru.
Seperti yang disebutkan, jika Anda ingin melakukannya di tempat:
Hal lain. Anda dapat mencocokkan menggunakan ekspresi:
Semoga ini bisa membantu seseorang
sumber
\n
di string pengganti. Plain-vanili (POSIX)sed
tidak tidak mengerti\n
dalam string pengganti, namun, jadi ini tidak akan bekerja pada BSD atau MacOS-kecuali jika Anda telah menginstal GNU sed entah bagaimana. Dengan vanilla sed Anda dapat menyematkan baris baru dengan "melarikan diri" - yaitu, mengakhiri garis dengan garis miring terbalik, kemudian menekan [Enter] ( referensi , di bawah judul untuk[2addr]s/BRE/replacement/flags
). Ini berarti perintah sed Anda harus menjangkau beberapa baris di terminal.Varian awk:
sumber
1;
, lihat Mengapa "1" di awk mencetak baris saat ini?Saya memiliki tugas yang sama, dan tidak bisa mendapatkan solusi perl di atas untuk bekerja.
Ini solusinya:
perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf
Penjelasan:
Menggunakan ekspresi reguler untuk mencari baris di file /etc/mysql/my.cnf saya yang hanya berisi
[mysqld]
dan menggantinya dengan[mysqld] collation-server = utf8_unicode_ci
secara efektif menambahkan
collation-server = utf8_unicode_ci
baris setelah baris yang mengandung[mysqld]
.sumber
Saya harus melakukan ini baru-baru ini juga untuk Mac dan Linux OS dan setelah browsing melalui banyak posting dan mencoba banyak hal, menurut pendapat khusus saya, saya tidak pernah sampai ke tempat yang saya inginkan yaitu: solusi yang cukup sederhana untuk memahami menggunakan terkenal dan perintah standar dengan pola sederhana, satu liner, portabel, dapat diperluas untuk menambah lebih banyak kendala. Kemudian saya mencoba melihatnya dengan perspektif yang berbeda, saat itulah saya menyadari bahwa saya dapat melakukannya tanpa opsi "satu liner" jika "2-liner" memenuhi seluruh kriteria saya. Pada akhirnya saya datang dengan solusi ini. Saya suka itu bekerja di Ubuntu dan Mac yang ingin saya bagikan dengan semua orang:
Pada perintah pertama, grep mencari nomor baris yang berisi "foo", cut / head memilih kemunculan ke-1, dan kenaikan aritmatika menambahkan nomor baris kemunculan pertama sebanyak 1 karena saya ingin memasukkan setelah kemunculannya. Pada perintah kedua, ini merupakan edit file di tempat, "i" untuk menyisipkan: sebuah ansi-c mengutip baris baru, "bar", lalu baris baru lainnya. Hasilnya menambahkan baris baru yang mengandung "bar" setelah baris "foo". Masing-masing dari 2 perintah ini dapat diperluas ke operasi yang lebih kompleks dan pencocokan.
sumber