sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename
Saya mengharapkan sedskrip ini untuk menyisipkan tabdi depan setiap baris $filenametetapi sebenarnya tidak. Untuk beberapa alasan itu memasukkan sebagai tgantinya.
Karena sed dapat bervariasi antar platform (khususnya, BSD / MacOSX versus Linux), mungkin berguna untuk menentukan platform tempat Anda menggunakan sed.
Ah iya; untuk memperjelas: tidak semua versi sed mengerti \tdi bagian pengganti ekspresi (itu dikenali \tdi bagian pencocokan pola dengan baik)
John Weldon
3
awwwwwwwwwwwwwwwwwww, ok itu cukup menarik. Dan aneh. Mengapa Anda membuatnya mengenalinya di satu tempat tetapi tidak di tempat lain ...?
sixtyfootersdude
2
Dipanggil dari skrip, itu tidak akan berfungsi: tab akan diabaikan oleh sh. Misalnya, kode berikut dari skrip shell akan menambahkan $ TEXT_TO_ADD, tanpa membuatnya terlebih dahulu dengan tabulasi: sed "$ {LINE} a \\ $ TEXT_TO_ADD" $ FILE.
Anda berada di jalur yang benar dengan $'string'penjelasan yang kurang. Sebenarnya saya curiga, karena penggunaan yang sangat canggung sehingga Anda mungkin memiliki pemahaman yang tidak lengkap (seperti yang kebanyakan kita lakukan dengan bash). Lihat penjelasan saya di bawah ini: stackoverflow.com/a/43190120/117471
Bruno Bronosky
1
Ingatlah bahwa BASH tidak akan memperluas variabel seperti $TABdi dalam tanda kutip tunggal, jadi Anda harus menggunakannya tanda kutip ganda.
nealmcb
Berhati-hatilah saat menggunakan *tanda kutip ganda di dalam ... ini akan diperlakukan sebagai bola, bukan sebagai ekspresi reguler yang Anda inginkan.
levigroker
27
@sedit berada di jalur yang benar, tetapi agak canggung untuk mendefinisikan variabel.
Solusi (khusus pesta)
Cara untuk melakukan ini di bash adalah dengan meletakkan tanda dolar di depan string kutipan tunggal Anda.
$ echo -e '1\n2\n3'123
$ echo -e '1\n2\n3'| sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3'| sed $'s/.*/\t&/g'123
Jika string Anda perlu menyertakan ekspansi variabel, Anda dapat menggabungkan string yang dikutip seperti ini:
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3'| sed "s/.*/$timestamp"$'\t&/g'149123795811491237958214912379583
Kata-kata dalam bentuk $ 'string' diperlakukan secara khusus. Kata tersebut diperluas menjadi string , dengan karakter pelolosan garis miring terbalik diganti seperti yang ditentukan oleh standar ANSI C. Urutan escape dengan garis miring terbalik, jika ada, didekodekan ...
Hasil yang diperluas adalah kutipan tunggal, seolah-olah tanda dolar tidak ada.
Solusi (jika Anda harus menghindari pesta)
Menurut saya pribadi, sebagian besar upaya untuk menghindari bash itu konyol karena menghindari bashisme TIDAK * membuat kode Anda portabel. (Kode Anda akan kurang rapuh jika Anda shebang ke bash -eudaripada jika Anda mencoba menghindari bash dan penggunaan sh[kecuali Anda adalah ninja POSIX mutlak].) Tetapi daripada memiliki argumen religius tentang itu, saya hanya akan memberikan yang TERBAIK * jawaban.
$ echo -e '1\n2\n3'| sed "s/.*/$(printf '\t')&/g"123
Lucu sekali Anda menggunakan fitur khusus "GNU echo" (menafsirkan \ t sebagai karakter tab) untuk memecahkan bug khusus "BSD sed" (menafsirkan \ t sebagai 2 karakter terpisah). Agaknya, jika Anda memiliki "GNU echo", Anda juga akan memiliki "GNU sed". Dalam hal ini Anda tidak perlu menggunakan echo. Dengan BSD echo echo '\t'akan mengeluarkan 2 karakter terpisah. Cara portabel POSIX adalah dengan menggunakan printf '\t'. Inilah sebabnya saya katakan: Jangan mencoba membuat kode Anda portabel dengan tidak menggunakan bash. Ini lebih sulit dari yang Anda pikirkan. Menggunakan bashadalah hal paling portabel yang dapat dilakukan kebanyakan dari kita.
Bruno Bronosky
3
Anda tidak perlu menggunakan seduntuk melakukan substitusi padahal sebenarnya Anda hanya ingin menyisipkan tab di depan baris. Penggantian untuk kasus ini adalah operasi yang mahal dibandingkan dengan hanya mencetaknya, terutama saat Anda bekerja dengan file besar. Lebih mudah dibaca juga karena bukan regex.
sedtidak mendukung \t, atau urutan pelarian lainnya seperti \ndalam hal ini. Satu-satunya cara yang saya temukan untuk melakukannya adalah dengan benar-benar memasukkan karakter tab dalam skrip menggunakan sed.
Meskipun demikian, Anda mungkin ingin mempertimbangkan untuk menggunakan Perl atau Python. Berikut skrip Python singkat yang saya tulis yang saya gunakan untuk semua ekspresi reguler aliran:
Saya pikir orang lain telah menjelaskan ini cukup untuk pendekatan lain ( sed, AWK, dll). Namun, bashjawaban spesifik saya (diuji pada macOS High Sierra dan CentOS 6/7) mengikuti.
1) Jika OP ingin menggunakan metode cari-dan-ganti yang mirip dengan yang mereka usulkan semula, maka saya akan menyarankan penggunaan perluntuk ini, sebagai berikut. Catatan: garis miring terbalik sebelum tanda kurung untuk regex seharusnya tidak diperlukan, dan baris kode ini mencerminkan cara $1yang lebih baik untuk digunakan daripada \1dengan perloperator substitusi (misalnya per dokumentasi Perl 5 ).
2) Namun, seperti yang ditunjukkan oleh ghostdog74 , karena operasi yang diinginkan sebenarnya hanya menambahkan tab di awal setiap baris sebelum mengubah file tmp ke file input / target ( $filename), saya akan merekomendasikan perllagi tetapi dengan modifikasi berikut (s):
3) Tentu saja, file tmp tidak berguna , jadi lebih baik melakukan semuanya 'di tempat' (menambahkan -itanda) dan menyederhanakan semuanya menjadi satu baris yang lebih elegan dengan
Jawaban:
Tidak semua versi
sed
mengerti\t
. Cukup masukkan tab literal sebagai gantinya (tekan Ctrl- Vlalu Tab).sumber
\t
di bagian pengganti ekspresi (itu dikenali\t
di bagian pencocokan pola dengan baik)Menggunakan Bash Anda dapat memasukkan karakter TAB secara terprogram seperti ini:
sumber
$'string'
penjelasan yang kurang. Sebenarnya saya curiga, karena penggunaan yang sangat canggung sehingga Anda mungkin memiliki pemahaman yang tidak lengkap (seperti yang kebanyakan kita lakukan dengan bash). Lihat penjelasan saya di bawah ini: stackoverflow.com/a/43190120/117471$TAB
di dalam tanda kutip tunggal, jadi Anda harus menggunakannya tanda kutip ganda.*
tanda kutip ganda di dalam ... ini akan diperlakukan sebagai bola, bukan sebagai ekspresi reguler yang Anda inginkan.@sedit berada di jalur yang benar, tetapi agak canggung untuk mendefinisikan variabel.
Solusi (khusus pesta)
Cara untuk melakukan ini di bash adalah dengan meletakkan tanda dolar di depan string kutipan tunggal Anda.
Jika string Anda perlu menyertakan ekspansi variabel, Anda dapat menggabungkan string yang dikutip seperti ini:
Penjelasan
Dalam bash
$'string'
menyebabkan "ekspansi ANSI-C". Dan itulah yang sebagian besar dari kita harapkan ketika kita menggunakan hal-hal seperti\t
,\r
,\n
, dll Dari: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-QuotingSolusi (jika Anda harus menghindari pesta)
Menurut saya pribadi, sebagian besar upaya untuk menghindari bash itu konyol karena menghindari bashisme TIDAK * membuat kode Anda portabel. (Kode Anda akan kurang rapuh jika Anda shebang ke
bash -eu
daripada jika Anda mencoba menghindari bash dan penggunaansh
[kecuali Anda adalah ninja POSIX mutlak].) Tetapi daripada memiliki argumen religius tentang itu, saya hanya akan memberikan yang TERBAIK * jawaban.* Jawaban Terbaik? Ya, karena salah satu contoh kesalahan kebanyakan skrip shell anti-bash dalam kodenya adalah penggunaan
echo '\t'
seperti dalam jawaban @ robrecord . Itu akan bekerja untuk GNU echo, tapi tidak BSD echo. Itu dijelaskan oleh The Open Group di http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 Dan ini adalah contoh mengapa mencoba menghindari bashism biasanya gagal.sumber
Saya telah menggunakan sesuatu seperti ini dengan shell Bash di Ubuntu 12.04 (LTS):
Untuk menambahkan baris baru dengan tab, kedua saat pertama cocok:
Untuk mengganti pertama dengan tab, kedua :
sumber
\\t
dan tidak\t
.Gunakan
$(echo '\t')
. Anda membutuhkan tanda kutip di sekitar pola.Misalnya. Untuk menghapus tab:
sumber
echo '\t'
akan mengeluarkan 2 karakter terpisah. Cara portabel POSIX adalah dengan menggunakanprintf '\t'
. Inilah sebabnya saya katakan: Jangan mencoba membuat kode Anda portabel dengan tidak menggunakan bash. Ini lebih sulit dari yang Anda pikirkan. Menggunakanbash
adalah hal paling portabel yang dapat dilakukan kebanyakan dari kita.Anda tidak perlu menggunakan
sed
untuk melakukan substitusi padahal sebenarnya Anda hanya ingin menyisipkan tab di depan baris. Penggantian untuk kasus ini adalah operasi yang mahal dibandingkan dengan hanya mencetaknya, terutama saat Anda bekerja dengan file besar. Lebih mudah dibaca juga karena bukan regex.misalnya menggunakan awk
sumber
Saya menggunakan ini di Mac:
Menggunakan tautan ini untuk referensi
sumber
sed
tidak mendukung\t
, atau urutan pelarian lainnya seperti\n
dalam hal ini. Satu-satunya cara yang saya temukan untuk melakukannya adalah dengan benar-benar memasukkan karakter tab dalam skrip menggunakansed
.Meskipun demikian, Anda mungkin ingin mempertimbangkan untuk menggunakan Perl atau Python. Berikut skrip Python singkat yang saya tulis yang saya gunakan untuk semua ekspresi reguler aliran:
sumber
Alih-alih BSD sed, saya menggunakan perl:
sumber
Saya pikir orang lain telah menjelaskan ini cukup untuk pendekatan lain (
sed
,AWK
, dll). Namun,bash
jawaban spesifik saya (diuji pada macOS High Sierra dan CentOS 6/7) mengikuti.1) Jika OP ingin menggunakan metode cari-dan-ganti yang mirip dengan yang mereka usulkan semula, maka saya akan menyarankan penggunaan
perl
untuk ini, sebagai berikut. Catatan: garis miring terbalik sebelum tanda kurung untuk regex seharusnya tidak diperlukan, dan baris kode ini mencerminkan cara$1
yang lebih baik untuk digunakan daripada\1
denganperl
operator substitusi (misalnya per dokumentasi Perl 5 ).2) Namun, seperti yang ditunjukkan oleh ghostdog74 , karena operasi yang diinginkan sebenarnya hanya menambahkan tab di awal setiap baris sebelum mengubah file tmp ke file input / target (
$filename
), saya akan merekomendasikanperl
lagi tetapi dengan modifikasi berikut (s):3) Tentu saja, file tmp tidak berguna , jadi lebih baik melakukan semuanya 'di tempat' (menambahkan
-i
tanda) dan menyederhanakan semuanya menjadi satu baris yang lebih elegan dengansumber