Ganti satu karakter dengan yang lain di Bash

223

Yang perlu saya lakukan adalah mengganti spasi ( ) dengan titik ( .) dalam sebuah string dalam bash.

Saya pikir ini akan sangat sederhana, tapi saya baru jadi saya tidak tahu cara memodifikasi contoh yang serupa untuk penggunaan ini.

Brian Leishman
sumber

Jawaban:

390

Gunakan penggantian string shell inline. Contoh:

foo="  "

# replace first blank only
bar=${foo/ /.}

# replace all blanks
bar=${foo// /.}

Lihat http://tldp.org/LDP/abs/html/string-manipulation.html untuk lebih jelasnya.

Brian Clapper
sumber
1
Sementara solusi ini bagus ketika berhadapan dengan string pendek (kasus umum, saya kira) satu mungkin lebih suka truntuk string panjang. Pada sistem saya trmengungguli bash mulai dari string dengan lebih dari 1000karakter. Sepertinya kompleksitas waktu bash lebih buruk daripada linear. Sebuah tes kecil: x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}". Dengan panjang string 1M (= 2 ^ 20) trmengambil 0.04sdan bash 5.0.11 mengambil 17s. Dengan 2M trtake 0.07s(diharapkan) tetapi bash butuh 69s(4 kali lebih lama untuk dua kali panjang string).
Socowi
@ Socowi Bermain dengan 1Mb yang disimpan dalam variabel tidak benar-benar biasa! Hingga lebih dari 10Kb, bash tampaknya tetap lebih cepat daripada forking to tr! ... Tergantung pada memori yang tersedia dan sumber daya hw ... Tapi Anda benar !: Tergantung pada jenis pekerjaan yang harus dilakukan, alat khusus tetap lebih efisien!
F. Hauri
Untuk karakter yang lolos seperti baris baru, pastikan untuk mencari$'\n'
user2561747
75

Anda bisa menggunakan tr, seperti ini:

tr " " .

Contoh:

# echo "hello world" | tr " " .
hello.world

Dari man tr:

DESCRIPTION
     Menerjemahkan, memeras, dan / atau menghapus karakter dari input standar, menulis ke output standar.

aioobe
sumber
Meskipun ini berfungsi untuk pertanyaan seperti yang ditanyakan, itu kurang umum daripada jawaban yang diterima (yang bekerja pada penggantian karakter dan juga string arbitrer), dan juga melibatkan dan perintah eksternal.
Dan Dascalescu
2
Di sisi lain itu berfungsi pada file 2gb tanpa memuat semuanya ke dalam memori.
aioobe
Pertanyaannya adalah tentang "string dalam bash", bukan file besar yang sewenang-wenang.
Dan Dascalescu
52

Di bash, Anda bisa melakukan penggantian pola dalam string dengan ${VARIABLE//PATTERN/REPLACEMENT}konstruk. Gunakan adil /dan tidak //untuk menggantikan hanya kejadian pertama. Polanya adalah pola wildcard, seperti gumpalan file.

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'
Gilles 'SANGAT berhenti menjadi jahat'
sumber
24

Coba ini

 echo "hello world" | sed 's/ /./g' 
rampok
sumber
6

Gunakan substitusi parameter:

string=${string// /.}
Fritz G. Mehner
sumber
4

Coba ini untuk jalur:

echo \"hello world\"|sed 's/ /+/g'|sed 's/+/\/g'|sed 's/\"//g'

Ini menggantikan ruang di dalam string yang dikutip ganda dengan +bernyanyi, lalu menggantikan+ tanda dengan backslash, lalu menghilangkan / mengganti tanda kutip ganda.

Saya harus menggunakan ini untuk mengganti spasi di salah satu jalur saya di Cygwin.

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'
dsrdakota
sumber
2
Sudah ada jawaban dua tahun yang menyelesaikan masalah sed. Kutipan tidak relevan.
chepner