dan ganti semua tab dan spasi dengan satu ruang

23

Saya mendapat string seperti berikut:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

sekarang saya ingin mengganti semua tab / spasi di antara catatan hanya dengan satu ruang sehingga saya dapat dengan mudah menggunakannya dengan cut -d " "

Saya mencoba yang berikut ini:

sed "s/[\t[:space:]]+/[:space:]/g"

dan berbagai variasi tetapi tidak bisa membuatnya bekerja. Ada ide?

Zulakis
sumber
Coba: sed -r -e "s / [\ t \] + / / g"
RJS
Apakah opsi cutdukungan Anda -w?
Kondybas

Jawaban:

40

Menggunakan sed -e "s/[[:space:]]\+/ /g"

Berikut penjelasannya:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

Untuk pengganti Anda, Anda hanya ingin memasukkan spasi. [:space:]tidak akan bekerja di sana karena itu adalah singkatan untuk kelas karakter dan mesin regex tidak akan tahu karakter apa yang harus diletakkan di sana.

Itu +harus melarikan diri dalam regex karena dengan mesin regex sed +adalah karakter normal sedangkan \+merupakan metacharacter untuk 'satu atau lebih'. Di halaman 86 dari Mastering Regular Expressions , Jeffrey Friedl menyebutkan dalam catatan kaki bahwa ed dan grep menggunakan tanda kurung yang lolos karena "Ken Thompson merasa ekspresi reguler akan digunakan untuk bekerja terutama dengan kode C, di mana perlu mencocokkan tanda kurung mentah akan lebih umum daripada referensi ulang. . " Saya berasumsi bahwa dia merasakan hal yang sama tentang tanda plus, maka kebutuhan untuk menghindarinya untuk menggunakannya sebagai metacharacter. Sangat mudah untuk tersandung oleh ini.

Dalam sed Anda harus melarikan diri +, ?, |, (, dan ). atau gunakan -r untuk menggunakan regex yang diperluas (kemudian terlihat seperti sed -r -e "s/[[:space:]]\+/ /g"ataused -re "s/[[:space:]]\+/ /g"

Bintang laut
sumber
Apakah ini juga menghapus tab? Bisakah Anda menjelaskan mengapa Anda menggunakan \+bukan hanya +?
Zulakis
Baiklah saya mengerti. [[: space:]] sama dengan [\ t \ r \ n \ v \ f]. Tapi bisakah Anda jelaskan mengapa Anda menggunakan\+
Zulakis
3
[[: space:]] setara dengan '\ s', jadi versi yang lebih pendek adalah "s / \ s \ + / / g"
3molo
2
Ekspresi reguler dasar menggunakan garis miring terbalik sebelum tanda tambah ketika digunakan untuk berarti "satu atau lebih dari karakter atau grup sebelumnya", sumber developer.apple.com/library/mac/#documentation/opensource/… .
3molo
Ahh, aku mengerti! Saya tidak tahu bahwa ada versi regex yang berbeda. Terima kasih
Zulakis
6

Anda dapat menggunakan opsi -s("pemerasan") dari tr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

Kelas [:blank:]karakter terdiri dari spasi dan tab.

Benjamin W.
sumber
-2

Saya suka menggunakan alias berikut untuk bash. Membangun apa yang orang lain tulis, gunakan sed untuk mencari dan mengganti beberapa spasi dengan satu spasi. Ini membantu mendapatkan hasil yang konsisten dari potongan. Pada akhirnya, saya menjalankannya melalui sed sekali lagi untuk mengubah ruang ke tab sehingga lebih mudah dibaca.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
Keamanan CNS direkam
sumber
Bagaimana ini menjawab pertanyaan?
Tonin