Saya menemukan bahwa \n
itu tidak bekerja di bawah Mac OS X. Secara khusus, katakan saya ingin memecah kata-kata yang dipisahkan oleh satu spasi menjadi garis-garis:
# input
foo bar
Saya menggunakan,
echo "foo bar" | sed 's/ /\n/'
Tapi hasilnya bodoh, \n
tidak luput!
foonbar
Setelah saya berkonsultasi ke google, saya menemukan solusinya :
echo 'foo bar' | sed -e 's/ /\'$'\n/g'
Setelah membaca artikel itu, saya masih tidak mengerti apa \'$'\n/g'
artinya. Bisakah seseorang menjelaskannya kepada saya, atau jika ada cara lain untuk melakukannya? Terima kasih!
echo "foo bar" | tr ' ' '\n'
\n
.Jawaban:
Anda dapat
brew install gnu-sed
dan mengganti panggilansed
dengangsed
.Jika Anda tidak ingin menambahkan "g" ke
sed
, Anda bisabrew install gnu-sed --with-default-names
dan cukup meneleponsed
.(Edit: bendera bir yang diperbarui, ujung topi ke Clément.)
sumber
--with-default-names
dan tidak--default-names
. Namun, opsi ini tidak berfungsi pada instalasi saya, jadi saya harus memasukkanalias gsed=sed
saya~/.profile
untuk membuatnya berfungsi.sed
pada OS X berperilaku seperti itu dan membuat asumsi yang salah yanggnu-sed
lebih benar. Jangan menjadi pecandu GNU dan tetap berpegang pada standar POSIX untuk menghindari masalah dalam jangka panjang.Ini juga akan bekerja:
echo 'foo bar' | sed $'s/ /\\\n/g'
lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"
Sed OS X tidak menginterpretasikan
\n
dalam pola ganti, tetapi Anda dapat menggunakan umpan baris literal yang diawali oleh karakter kelanjutan garis. Shell menggantikan$'\n'
dengan linefeed literal sebelum perintah sed dijalankan.sumber
sed $'s/ /\\\n/g'
berhasil, tetapi tidaksed $'s/\\\n/ /g'
?sed
bahkan di linux / unix untuk menghapus baris baru karena diuraikan / dibagi di setiap baris baru. Jika Anda menjalankan ini di linux / unix, itu tidak akan melakukan apa pun:echo -e 'foo\nbar' | sed 's/\n//'
Solusi yang Anda temukan melewati string argumen tunggal ke
sed -e
.Argumen itu akhirnya menjadi string dalam
s/ / /g
format sed yang umum .Tali itu dibuat dalam dua bagian, satu demi satu.
Bagian pertama dikutip dalam
'...'
bentuk.Bagian kedua dikutip dalam
$'...'
bentuk.Bagian
's/ /\'
mendapatkan tanda kutip tunggal dilucuti, tetapi sebaliknya melewati sed seperti yang terlihat pada baris perintah. Artinya, backslash tidak dimakan oleh bash, itu diteruskan ke sed.Bagian
$'\n/g'
mendapat tanda dolar dan tanda kutip tunggal dilepas, dan yang\n
dikonversi menjadi karakter baris baru.Secara keseluruhan, argumen menjadi
s / / \ newline/ g
[Itu tadi menyenangkan. Butuh waktu beberapa saat untuk membukanya. +1 untuk pertanyaan yang menarik.]
sumber
Ungkapannya
$'...'
adalahbash
-ism yang menghasilkan...
dengan urutan pelarian standar diperluas. Th\'
sebelum itu hanya berarti garis miring terbalik diikuti oleh akhir bagian yang dikutip, string yang dihasilkan adalahs/ /\
. (Ya, Anda dapat beralih mengutip di tengah-tengah string; itu tidak mengakhiri string.)Standar POSIX
sed
hanya menerima\n
sebagai bagian dari pola pencarian. OS X menggunakan FreeBSDsed
, yang sepenuhnya sesuai dengan POSIX; GNU, seperti biasa, menambahkan hal-hal tambahan dan kemudian pengguna Linux semua berpikir bahwa itu semacam "standar" (mungkin saya akan lebih terkesan jika salah satu dari mereka memiliki proses standar).sumber
$'...'
bagian itu. Tapi ... apa itus/ /\
? Apa maksudmuswitch quoting
?'...'
adalah salah satu jenis kutipan shell;$'...'
adalah yang lain. Ada juga"..."
dan\x
mengutip satu karakter. Anda dapat menggabungkan mereka dalam satu kata, yang sedang dilakukan di sana, beralih dari''
string normal ke$''
string untuk menerjemahkan\n
. Adapun sisanya, itu membangunsed
perintah (s/text/replacement/flags
). Dalam hal ini perintah dimulai, termasuk garis miring terbalik di akhir untuk melindungi baris baru literal yang$'\n/g'
ditambahkan. Hasilnya adalah untuk mengganti semua/g
spasi ( bendera) dengan baris baru.Ada yang sangat mudah untuk melihat secara visual apa yang terjadi. Cukup gema string!
hasil dalam
yang setara dengan
s/$/\
newline/g
Jika Anda tidak memiliki ekstra
\
sebelumnewline
, shell akan menafsirkannewline
sebagai akhir dari perintah sebelum waktunya.sumber