Ganti beberapa spasi dengan hanya menggunakan 'tr'


71

Saya punya file f1.txt,:

ID     Name
1      a
2         b
3   g
6            f

Jumlah ruang tidak tetap. Apa cara terbaik untuk mengganti semua ruang putih dengan hanya menggunakan satu ruang tr?

Inilah yang saya miliki sejauh ini:

cat f1.txt | tr -d " "

Tetapi hasilnya adalah:

IDName
1a
2b
3g
6f

Tapi saya ingin terlihat seperti ini:

ID Name
1 a
2 b
3 g
6 f

Silakan coba dan hindari sed.


6
Mengapa sangat penting untuk menghindari sed? Gunakan apa pun yang berhasil!
David Richerby

7
Karena saya tahu bagaimana melakukannya sed. Ingin tahu cara lain
:)

Jawaban:


106

Dengan tr, gunakan opsi pengulangan squeeze :

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

Atau Anda dapat menggunakan awksolusi:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

Saat Anda mengubah bidang dalam rekaman, awkmembangun kembali $0, mengambil semua bidang dan menyatukannya, dipisahkan oleh OFS, yang merupakan ruang secara default.

Itu akan memeras urutan spasi dan tab (dan mungkin karakter kosong lainnya tergantung pada lokal dan implementasi awk) menjadi satu ruang, tetapi juga menghapus blanko terkemuka dan tertinggal dari setiap baris.


1
Ini juga solusi hebat. . . Saya tidak tahu yang mana yang harus dipilih sekarang: / @Gnouc
gkmohit

Jangan ragu untuk memilih solusi apa pun yang Anda suka dan itu bekerja untuk Anda. Catatan bahwa solusi saya berbeda dengan jawaban @ polym.
cuonglm

1
:)) yay! Jawaban @Gnouc benar-benar dinamis, karena dia menggunakan awk, dia bisa melakukan apa saja. Anda juga dapat menerima solusinya. Hanya satu hal: Gnouc dapatkah Anda menjelaskan apa format awk dalam perintah Anda? Dapatkah Anda menambahkan tab / spasi sehingga hasilnya sesuai dengan hasil yang diharapkan dari Unknown?
Polym

1
@ polym: Dengan edit terakhir Unknown, ia tampaknya hanya menginginkan satu spasi, bukan keluaran seperti column -thalnya. Tambahkan penjelasan untuk awk.
cuonglm

4
Ada perbedaan kecil di sini. trakan mengganti dua spasi di ujung garis dengan satu spasi. awkakan menghapus semua spasi tambahan.
Anne van Rossum

19

Cukup gunakan column:

column -t inputFile

Keluaran:

ID  Name
1   a
2   b
3   g
6   f

Hebat dan balasan cepat :)
gkmohit

1
@ Tidak Diketahui Hebat siap melayani :)!
Polym

1
@ Gnouc wow keren, kolom juga mengambil file sebagai argumen. Terima kasih banyak!
Polym

Bagaimana saya bisa mendapatkan kolom kedua hanya jika saya mau? Saya mencoba column -t f1.txt | cut -d " " -f2 Tapi itu bukan solusi yang saya harapkan
gkmohit

2
Gunakan awk then: column -t file | awk '{print $2}'mencetak kolom kedua saja
polym

8

Jika Anda ingin memeras "spasi putih" Anda akan ingin menggunakan set karakter yang telah ditentukan sebelumnya tr:: blank: "(tab dan spasi spasi putih horisontal) atau": spasi: "(spasi putih verical):

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

Contoh dijalankan pada Red Hat 5 (GNU tr).

Dalam kasus saya, saya ingin menormalkan semua spasi putih menjadi satu ruang sehingga saya bisa mengandalkan ruang sebagai delmitter.

Seperti yang ditunjukkan oleh komentar kedua dastrobu, saya melewatkan kata-kata di halaman manual:

 -s uses the last specified SET, and occurs after translation or deletion.

Ini memungkinkan kita untuk menghilangkan tr pertama. Kudo untuk bersabar atas kesabarannya di hadapan kepadatanku.

Sebelumnya, parsing port dari Redis config. mengajukan:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

Setelah, dengan SET2 ditentukan dengan pemerasan:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

Keluaran:

6379

Untuk lebih jelasnya mencakup nuansa whitespace

Tunjukkan di mana squeeze saja gagal ketika karakter campuran berturut-turut yang termasuk dalam kelas karakter [: blank:] terlibat:

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

Catatan: Dua bidang string saya dalam format printf dipisahkan oleh 1 spasi, 1 tab, 1 spasi. Setelah ditekan urutan ini masih ada. Dalam output dump Octal ini diwakili oleh urutan ascii 040 011 040.


1
Apakah Anda benar-benar membutuhkan tr "[:blank:]" " " | tr -s "[:blank:]"? Saya kira bagian pertama sudah cukup, yaitu tr "[:blank:]" " "karena itu menormalkan spasi dan sudah melakukan substitusi. Dari halaman manual: "Peras beberapa kejadian karakter [...] Ini terjadi setelah semua penghapusan dan terjemahan selesai."
dastrobu

2
jadi ´tr -s "[: blank:]" "" ´ harus melakukannya terlebih dahulu menerjemahkan semua kosong ke spasi dan kemudian meremas spasi. Tidak perlu ´tr´ kedua.
dastrobu

1
Saya mencoba printf 'ID \t Name\n' | tr -s "[:blank:]" " " | od -cb(seperti yang disarankan oleh @dastrobu) dan saya mendapat ID Name\n(dengan satu spasi) sebagai keluaran. Apakah Anda benar-benar mencobanya, @ user3183018?
Scott

1
Oke, izinkan saya mencoba mengatakan ini lagi. Saya lakukan printf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"  (seperti yang disarankan oleh @dastrobu), di mana merupakan spasi, dan saya mendapat ID␣Name\n(dengan satu spasi) sebagai output. Ini persis sama dengan contoh Anda tentang "Port <SPACE> <TAB> <SPACE> 6379" kecuali saya menggunakan string heading dari pertanyaan. Saya ingin tahu apakah Anda mencoba  tr -s "[:blank:]"(tanpa "␣"argumen terakhir ).
Scott

1
Ketika saya melakukannya printf 'ID \t Name\n' | od -cb, itu menunjukkan apa yang seharusnya: ID ⁠  \t ⁠  N a m e \n(yaitu,  ID 040 011 040 N a m e\n). Sementara itu, dengan bukti Anda sendiri, Anda membuat kesalahan yang saya duga adalah: Anda menjalankan tr -s "[:blank:]"(yaitu,  trdengan satu opsi dan  satu argumen), alih-alih perintah yang @dastrobu dan saya presentasikan empat kali sekarang: tr -s '[:blank:]' '␣'(Yaitu,  trdengan satu opsi dan  dua argumen ).
Scott

5

Siapa yang butuh program (selain shell)?

while read a b
do
    echo "$a $b"
done < f1.txt

Jika Anda ingin nilai di kolom kedua berbaris, seperti dalam columnjawaban polym , gunakan printfsebagai ganti echo:

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt

1
Pertama-tama, bila dibandingkan dengan tr - ini adalah saran yang sangat lemah dari segi efisiensi kecuali jika inputnya terlalu kecil terlalu besar daripada biaya trseruan yang kecil - yang belum lagi berapa banyak pekerjaan yang diperlukan untuk menulis. Terakhir, bukankah Anda akan mengatakan bahwa posting ini tidak benar-benar menjawab pertanyaan sebagaimana ditanyakan? Apa cara terbaik untuk mengganti semua ruang putih dengan satu ruang hanya menggunakan tr?
mikeserv

1
Dan selain itu - tidak bisakah Anda lebih mudah melakukan sesuatu $IFS? Mungkin seperti: IFS=' <tab>' set -f ; echo $(cat <file)?
mikeserv

2

Ini adalah pertanyaan lama dan dipecahkan berkali-kali. Hanya untuk kelengkapan: Saya punya masalah serupa, tetapi ingin melewati jalur melalui pipa ke program lain. Saya menggunakan xargs .

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

jadi cat f1.txt | xargs -L1sepertinya output persis apa yang Anda inginkan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.