Ini seharusnya sangat sederhana, tetapi untuk beberapa alasan itu tidak berfungsi:
sed -i.bak -E 's/\t/ /' file.txt
Alih-alih mengganti karakter tab, itu menggantikan t
karakter. Saya telah mencoba setiap variasi dalam hal ini yang dapat saya pikirkan, bermain dengan mengutip, dll. Saya telah mencari di Google dan menemukan orang lain menggunakan ekspresi yang sangat mirip dan mereka sepertinya bekerja untuk mereka.
Ini -E
adalah hal OS X. Saya pikir kegagalan itu mungkin hasil dari beberapa kekhasan aneh OS X sed
, jadi saya mencobanya dengan Ruby juga (tanpa -i
), dan mendapat hasil yang sama:
ruby -pe '$_.gsub!(/\t/," ")' < file.txt > file.new
Saya menggunakan Bash 3.2.51 pada OS X, dan iTerm, meskipun saya tidak dapat melihat bagaimana hal itu sangat relevan. Saya belum menetapkan variabel lingkungan aneh, meskipun saya dapat memposting apa pun yang menurut Anda mungkin relevan.
Apa yang salah?
UPDATE : Saya harus telah membuat beberapa kesalahan lain atau salah ketik ketika saya mencoba versi Ruby, karena Gilles menunjukkan bahwa itu tidak bekerja (dan saya tidak pernah memiliki dia mengarahkan saya salah!). Saya tidak yakin apa yang terjadi, tetapi saya cukup yakin itu pasti kesalahan saya.
sumber
\t
dalamsed
pernyataan denganCTRL-V<TAB>
mana<TAB>
adalah kunci tab danCTRL-V
merupakan kunci kontrol danv
ditekan bersama-sama.Jawaban:
Sintaks
\t
untuk karakter tab di sed tidak standar. Pelarian itu adalah ekstensi sed GNU . Anda menemukan banyak contoh online yang menggunakannya karena banyak orang menggunakan GNU sed (ini adalah implementasi sed pada Linux yang tidak tertanam). Tapi OS X sed , seperti sed * BSD lainnya, tidak mendukung\t
tab dan malah memperlakukan\t
sebagai backslash yang diikuti oleht
.Ada banyak solusi, seperti:
Gunakan karakter tab literal.
Gunakan
tr
atauprintf
untuk menghasilkan karakter tab.Gunakan sintaks string bash yang memungkinkan backslash lolos .
Gunakan Perl, Python atau Ruby. Cuplikan Ruby yang Anda poskan tidak berfungsi.
sumber
...sed
skrip (digunakan melalui-f
opsi), karakter tab literal sepertinya satu-satunya kemungkinan bagi saya. Saat mengedit ini dengan vim,set noexpandtab
penting.tr
teknik itu jika Anda ingin rekan kerja Anda menusuk wajah Anda ketika mereka membaca naskah Anda.sed $'s/<regex>/\t/' file.txt
berfungsi untuk menyisipkan, tetapi$
tampaknya melanggar skrip saya ketika saya mencoba untuk memasukkan bagian dari regex dalam substitusi saya, yaitused $'s,\(ontology/[0-9]\+\),\t\txxx\1xxx\t\t,'
memberikan `xxxxxx` dengan nilai kecocokan yang diharapkan diganti dengan` `. Apakah ada yang setara dengan\1
saat menggunakan sintaks string bash? Sunting: seharusnya ada karakter unicode U + 231C di tengah xxx <U + 231C> xxx.Gunakan kutipan spesifik Bash yang memungkinkan Anda menggunakan string seperti dalam C, sehingga karakter tab nyata diteruskan ke sed, bukan urutan escape:
sumber
bekerja untuk saya di OS X dan merupakan perintah yang sama saya gunakan di linux sepanjang waktu.
sumber
Seperti dicatat, tidak semua
sed
implementasi mendukung notasi\t
sebagai tab horizontal.Anda dapat dengan mudah mencapai substitusi dengan:
Ini melakukan penggantian in situ yang menyimpan file asli Anda sebagai "* .old". Perl memungkinkan pembatas alternatif untuk klasik
/
membuat ekspresi jauh lebih mudah dibaca (yaitu tanpa sindrom "condong tusuk gigi").The
+
mengatakan satu atau lebih pengulangan karakter tab harus diganti. Theg
pengubah memungkinkan penggantian global sepanjang akhir setiap baris.sumber
Anda juga dapat menggunakan
echo
di dalamsed
:sed -i "s/$(echo '\t')//g"
sumber
echo '\t'
hanya akan menampilkan\t
implementasi beberapa shell dariecho
.Jika Anda ingin yang lebih kuat
sed
(mendukung\t
dan lebih) daripada yang ada di OS X, instal GNU sed .sumber
sed
adalah masalahnya. Apakah Anda punya alasan untuk percaya bahwa itulah masalahnya? Saya akan senang menginstal sed GNU jika saya punya alasan untuk percaya itu akan menyelesaikan masalah, tetapi sepertinya saya sudah cukup banyak mengesampingkan itu.ruby -pe '$_.gsub!(/\t/," ")' < file.txt
Jika tidak apa-apa untuk meminta
bash
atauzsh
sebagai shell, maka ini adalah solusi termudah yang dapat saya pikirkan:Namun perlu dicatat bahwa
echo
flag (-n
dan-e
) tidak terdefinisi dalam POSIX, sehingga shell sesuai POSIX tidak perlu memahami flag tesis ini, namun banyak yang akan karena alasan kompatibilitas.sumber
Saya terkejut tidak ada yang menyarankan solusi yang sangat sederhana:
sed -i.bak -E 's/\\\t/ /' file.txt
Itu harus melakukan trik.Anda perlu melarikan diri dari pelarian (karenanya 3 \ s) untuk memungkinkan sed memahami bahwa Anda mencoba menggunakan karakter dalam ekspresi reguler ketika semuanya diganti ...
sumber
sed
, satu\
sudah cukup, karena tidak perlu melarikan diri. Masalahnya adalah bahwa BSDsed
tidak mendukung sintaks ini untuk tab.Ini berhasil untuk saya.
sed -e 's / [\ t] / / g'
sumber
sed
. Ini bukan yang digunakan OP.