Bagaimana menemukan dan mengganti string tanpa menggunakan perintah Sed?

16

Seperti yang kita semua tahu, sedadalah sangat efisien untuk mencari dan mengganti string, misalnya menemukan 'a' dan menggantinya dengan 'b': sed 's/a/b/g'.

Apakah mungkin melakukan ini dengan perintah lain atau skrip shell bukan sed?

Ini untuk sistem linux yang dipangkas untuk TV yang tidak memiliki sedperintah. Jadi saya harus menggunakan perintah atau skrip lain, bukansed 's/a/b/g'. –

binghenzq
sumber
Sebenarnya, itu hanya substitusi berbasis ekspresi reguler. Setiap alat atau bahasa mampu menangani hal tersebut akan dapat melakukan hal yang sama, tetapi dengan berbagai sintaks: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Selain itu, banyak alat dan bahasa juga dapat melakukan penggantian string teks biasa. Jadi pertanyaan Anda entah bagaimana luas.
manatwork
1
Mengapa? Masalah apa yang Anda sedang coba pecahkan?
Gilles 'SANGAT berhenti menjadi jahat'
Sistem linux yang dipangkas untuk TV tidak memiliki perintah. Jadi saya harus menggunakan perintah atau skrip lain sebagai ganti sed 's / a / b / g'.
binghenzq

Jawaban:

12

Ya ada berbagai cara untuk melakukan ini. Anda dapat menggunakan awk,, perlatau bashmelakukan aktivitas ini juga. Meskipun secara umum sedmungkin merupakan alat yang paling tepat untuk melakukan tugas-tugas jenis ini.

Contohnya

Katakanlah saya punya data sampel ini, dalam file data.txt:

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

awk

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Pengeditan sebaris

Contoh di atas dapat langsung memodifikasi file juga. Contoh Perl adalah sepele. Cukup tambahkan -isakelar.

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Untuk awkitu sedikit kurang langsung tetapi sama efektifnya:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Metode ini membuat sub-shell dengan kurung kurawal '{...} `di mana file diarahkan ke dalamnya melalui ini:

$ { ... } < data.txt

Setelah file diarahkan ke sub-shell, itu dihapus dan kemudian awkdijalankan terhadap konten file yang dibaca ke dalam sub-shell STDIN. Konten ini kemudian diproses oleh awkdan ditulis kembali ke nama file yang sama yang baru saja kita hapus, menggantikannya secara efektif.

slm
sumber
Terima kasih atas jawaban Anda dan saya akan mencobanya hari kerja berikutnya. Tetapi saya tidak yakin apakah itu berfungsi karena beberapa perintah mungkin tidak ada di sistem linux TV yang dipangkas, seperti 'sed'. Jadi saya masih ingin menggunakan perintah' cari ' , 'grep' dan sebagainya untuk menyelesaikannya.
binghenzq
@binghenzq - Saya telah menambahkan contoh yang inline mengedit file.
slm
-1 Saya jarang mengundurkan diri tetapi dalam kasus ini inti dari pertanyaan tersebut tampaknya merupakan metode yang lebih sederhana daripada metode lain yang lebih rumit dan mungkin juga tergantung. Jika pertanyaannya hanya tentang alternatif untuk instalasi mesin * nix penuh maka saya mungkin akan memberi ini +1 jawaban yang baik.
Michael Durrant
@MichaelDurrant - Saya baru saja menambahkan suntingan inline rumit itu b / c OP meminta mereka. Juga OP menetapkan persyaratan untuk TIDAK menggunakan sedbukan saya. Sed adalah alat yang tepat untuk melakukan pergantian seperti ini, dan dia jelas meminta untuk lebih memahami peran alat-alat ini, jadi menunjukkan kepada seseorang hal-hal ini meskipun buruk, sangat pendidikan dalam menunjukkan mereka kenapa. Terlalu sering orang yang tahu hanya mengatakan "jangan lakukan itu" tanpa menjelaskan alasannya, jadi saya. Tetapi terima kasih untuk setidaknya meninggalkan komentar mengapa Anda DV.
slm
Tentu, saya pikir itu adalah jawaban yang bagus dalam semua hal lainnya. ya saya benci -1 tanpa penjelasan.
Michael Durrant
13

Alternatif klasik untuk penggantian satu huruf adalah trperintah yang harus tersedia di hampir semua sistem:

$ echo "foobar" | tr a b   
foobbr

trlebih baik daripada seduntuk ini sebenarnya karena menggunakan sed(apalagi perlatau awk) untuk penggantian huruf tunggal seperti menggunakan palu godam untuk membunuh seekor lalat.

grep tidak dirancang untuk ini, tidak mengubah inputnya, hanya mencari melalui itu.

Atau, Anda dapat menggunakan kemampuan substitusi dari beberapa shell. Di sini menggunakan ksh, zshatau bashsintaks:

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Kami dapat memberikan jawaban yang lebih spesifik jika Anda menjelaskan dengan tepat masalah apa yang Anda coba selesaikan.

terdon
sumber
Apakah ada opsi untuk mengabaikan kasus ${foo//a/b}?
AlikElzin-kilaka
@ AlikElzin-kilaka aku takut tidak. Anda harus menggunakan sesuatu yang lebih canggih seperti, misalnya: echo "$foo" | sed 's/a/b/iatau memberikan kelas karakter: echo ${foo//[aA]/b}.
terdon
4

Anda dapat menggunakan Vim dalam mode Ex:

ex -s -c '%s/a/b/g|x' file
  1. % pilih semua baris

  2. s pengganti

  3. g ganti global

  4. x Simpan dan tutup

Steven Penny
sumber
Terima kasih banyak. hanya untuk menambahkan, flag -c adalah untuk mengeksekusi perintah ketika pengeditan dimulai (karena ex adalah editor) dan flag -s adalah mode skrip yang menonaktifkan umpan balik atau seperti beberapa orang mengatakan slient-mode. ref untuk info lebih lanjut: ex-vi.sourceforge.net/ex.html
Jimmy MG Lim
3

Jika Anda bekerja dengan file daripada sungai, Anda bisa menggunakan editor teks standar, ed:

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Ini harus tersedia pada * nix apa pun. Tanda koma ',s/a/b/g'memberi tahu eduntuk bekerja pada setiap baris (Anda juga dapat menggunakan %, yang akan lebih akrab jika Anda terbiasa vim), dan sisanya adalah pencarian standar dan ganti. wmemintanya untuk menulis (menyimpan) file, qmemintanya untuk keluar.

Perhatikan bahwa, tidak seperti -iopsi sed (dan opsi serupa di alat lain), ini sebenarnya mengedit file di tempat daripada curang dengan file sementara.

Saya tidak berpikir itu mungkin untuk mendapatkan ini bekerja dengan aliran, tapi kemudian saya tidak benar-benar tahu banyak tentang eddan saya tidak akan terkejut jika itu benar-benar memiliki kemampuan itu (filosofi unix menjadi apa adanya).

Evilsoup
sumber
2

Menggunakan perintah leluhur (yang -sberarti tenang (silent) dan koma sebelum perintah berarti mengeksekusi di semua baris):

Hanya mencetak pada STDOUT :

ed -s file <<!
,s/a/b/g
,p
q
!

mengganti di tempat:

ed -s file <<!
,s/a/b/g
w
q
!
Gilles Quenot
sumber