apakah berperilaku berbeda di FreeBSD dan di Linux?

12

Saya menggunakan Linux dan FreeBSD (khususnya, saya menggunakan Debian Linux dan PC-BSD), dan saya menemukan sesuatu yang aneh sed.

Saya sering perlu mengonversi file "nilai yang dipisahkan tab" menjadi "nilai yang dipisahkan koma". Cara paling sederhana yang saya tahu adalah menggunakan sed, seperti ini:

sed 's/\t/,/g' inputFile.txt > outputFile.csv

Ini berfungsi dengan baik di Linux: Ia mengganti setiap tab dengan koma ... tetapi di FreeBSD, itu tidak menggantikan apa pun !!!

Apakah saya melewatkan sesuatu? Apakah ada sintaks dengan FreeBSD sedyang berbeda dengan yang ada di Linux?

Barranka
sumber

Jawaban:

9

Mungkin Anda harus menggunakan -Eopsi (atau -rseperti yang dijelaskan pada manual ) untuk menjaga kompatibilitas dengan GNU Sed. Dalam kasus Anda, Anda dapat menginstal Gnu Sed jika Anda terbiasa (porta ports gsed di FreeBSD), atau akan membutuhkan upaya yang lama untuk port script.

Dan ingatlah. Jika beberapa perintah pada BSD tidak bertindak seperti versi gnu dari utilitas itu, itu tidak berarti itu rusak;)


sumber
1
Terima kasih. The -Epilihan membuat trik (baik di FreeBSD dan Mac OS X).
Barranka
Pada FreeBSD 9 saya, opsi -E tidak membantu.
Ark-kun
6

Ya, ada berbagai perbedaan, perilaku-i menjadi satu-satunya yang saya tahu dari atas kepala saya.

Saya tidak pernah menggunakan BSD jadi saya benar-benar tidak bisa membantu dengan rincian tetapi solusi mungkin untuk digunakan trsebagai gantinya:

tr '\t' , < inputFile.txt > outputFile.csv

Efek samping yang menyenangkan adalah yang trseharusnya lebih cepat secara signifikan. Saya mengujinya di Linux saya menggunakan file uji dengan 50000 baris, yang masing-masing memiliki 2 tab:

$ time tr '\t' , < foo.txt > /dev/null 

real    0m0.004s
user    0m0.000s
sys     0m0.000s

$ time sed 's/\t/,/g' foo.txt > /dev/null 

real    0m0.039s
user    0m0.036s
sys     0m0.000s
terdon
sumber
tr '\t' ,lebih portabel daripada tr $'\t' ,. tr '[\t]' '[,]'bahkan akan portabel untuk beberapa sistem SysV lama.
Stéphane Chazelas
tab adalah pembatas default untuk cut. POSIX spec untuk tradalah ada . Saya salah tentang [dibutuhkan untuk SysV tua. Karena spesifikasi POSIX menunjukkan [hanya diperlukan untuk rentang di sana.
Stéphane Chazelas
@StephaneChazelas, ya, maaf tidak yakin apa yang membuat saya bingung saat itu. Bagaimanapun, terima kasih atas klarifikasi.
terdon
4

Ya, tidak seperti GNU sed FreeBSDsed tidak menafsirkan urutan pelarian ANSI C seperti \tdalam ekspresi reguler.

Salah satu cara untuk mendapatkan denomiator yang paling tidak umum dalam hal ini adalah menggunakan printf .

tab="$(printf '\t')"
printf '\t\n' | sed 's/'"${tab}"'/,/g'
printf '\t\n' | sed 's/'"$(printf '\t')"'/,/g'

Perilaku sed -ipengeditan file in-place dapat dibuat kompatibel jika sebuah switch atau opsi segera mengikuti -iswitch, mis. sed -i -e 's/x/X/g' fileBerfungsi baik untuk GNU sedmaupun FreeBSD sed.

Versi FreeBSD terbaru sed(FreeBSD 8.1 atau yang lebih baru) memiliki -rperalihan untuk meningkatkan kompatibilitas dengan GNU sed.

(Selain itu, penggunaan kelas karakter POSIX dalam sedekspresi reguler adalah cara yang baik untuk memastikan kompatibilitas juga).

Untuk alternatif, sedimplementasi POSIX-conformant lihat: minised - implementasi SED yang lebih kecil, lebih murah, lebih cepat .

kroy
sumber
3

Anda harus menggunakan TABkarakter literal alih-alih \t:

sed 's/    /,/g' inputFile.txt > outputFile.csv

Lihat komentar ini oleh Stephane pada pertanyaan lain.

Artikel berikut juga mungkin menarik bagi Anda:

Saya mengutip bagian yang relevan:

Perbedaan Regex

Sintaks ekspresi reguler berbeda secara halus antara versi SED yang berbeda. Sebagian besar perbedaan melibatkan pola pelarian khusus yang digunakan untuk mencocokkan karakter yang tidak dicetak, seperti bel ASCI dan umpan formulir.

Joseph R.
sumber
0

Setelah masuk saya melihat pengumuman selanjutnya dan menyimpannya. Semoga bermanfaat bagi yang lain juga

Ingin menggunakan sed (1) untuk mengedit file di tempat? Nah, untuk mengganti setiap 'e' dengan 'o', dalam file bernama 'foo', Anda dapat melakukan:

sed -i.bak s/e/o/g foo

Dan Anda akan mendapatkan cadangan dari aslinya dalam file bernama 'foo.bak', tetapi jika Anda tidak menginginkan cadangan:

sed -i '' s/e/o/g foo
TradeNarK
sumber
yang -ipilihan itu tertutup sudah , meskipun
Jeff Schaller