sed thay thế tất cả các tab và không gian bằng một không gian duy nhất


23

Tôi có một chuỗi như sau:

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

bây giờ tôi muốn thay thế tất cả các tab / khoảng trắng giữa các bản ghi chỉ bằng một khoảng trống để tôi có thể dễ dàng sử dụng nó với cut -d " "

Tôi đã thử như sau:

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

và nhiều phương sai khác nhau nhưng không thể làm cho nó hoạt động. Có ý kiến ​​gì không?


Hãy thử: sed -r -e "s / [\ t \] + / / g"
RJS

cuthỗ trợ -wtùy chọn của bạn ?
Kondybas

Câu trả lời:


40

Sử dụng sed -e "s/[[:space:]]\+/ /g"

Đây là một lời giải thích:

[   # 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).

Để thay thế, bạn chỉ muốn chèn một khoảng trắng. [:space:]sẽ không hoạt động ở đó vì đó là tên viết tắt của một lớp nhân vật và công cụ regex sẽ không biết nhân vật nào được đặt ở đó.

Các +phải được thoát ra trong regex vì với động cơ regex sed của +là một nhân vật bình thường trong khi \+là một metacharater cho 'một hoặc nhiều'. Trên trang 86 của Làm chủ các biểu thức chính quy , Jeffrey Friedl đã đề cập đến một chú thích rằng ed và grep đã sử dụng dấu ngoặc đơn thoát vì "Ken Thompson cảm thấy các biểu thức chính quy sẽ được sử dụng để làm việc chủ yếu với mã C, trong đó việc khớp với dấu ngoặc thô sẽ phổ biến hơn so với phản hồi ngược . " Tôi cho rằng anh ta cũng cảm thấy như vậy về dấu cộng, do đó cần phải thoát khỏi nó để sử dụng nó như một siêu vi khuẩn. Thật dễ dàng để vượt qua điều này.

Trong sed bạn sẽ cần phải thoát khỏi +, ?, |, (, và ). hoặc sử dụng -r để sử dụng regex mở rộng (sau đó có vẻ như sed -r -e "s/[[:space:]]\+/ /g"hoặcsed -re "s/[[:space:]]\+/ /g"


Điều này cũng loại bỏ các tab? Bạn có thể giải thích tại sao bạn sử dụng \+thay vì chỉ +?
Zulakis

Được rồi tôi hiểu rồi. [[: space:]] bằng [\ t \ r \ n \ v \ f]. Nhưng bạn có thể vui lòng giải thích lý do tại sao bạn sử dụng\+
Zulakis

3
[[: space:]] tương đương với '\ s', vì vậy phiên bản ngắn hơn là "s / \ s \ + / / g"
3molo

2
Các biểu thức chính quy cơ bản sử dụng dấu gạch chéo ngược trước dấu cộng khi được sử dụng có nghĩa là một hoặc nhiều ký tự hoặc nhóm trước đó, nguồn developer.apple.com/l Library / mac / # document / optource / xóa .
3molo

À, tôi hiểu rồi! Tôi không biết rằng có các phiên bản regex khác nhau. Cảm ơn
Zulakis

6

Bạn có thể sử dụng -stùy chọn ("bóp") của 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

Lớp [:blank:]nhân vật bao gồm cả không gian và tab.


-2

Tôi thích sử dụng bí danh sau đây cho bash. Dựa trên những gì người khác đã viết, sử dụng sed để tìm kiếm và thay thế nhiều không gian bằng một không gian duy nhất. Điều này giúp có được kết quả phù hợp từ cắt. Cuối cùng, tôi chạy nó qua sed một lần nữa để thay đổi không gian thành tab để dễ đọc hơn.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'

Làm thế nào điều này trả lời câu hỏi?
Tonin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.