sed hành xử khác nhau trên FreeBSD và trên Linux?


12

Tôi sử dụng cả Linux và FreeBSD (cụ thể, tôi sử dụng Debian Linux và PC-BSD) và tôi thấy có gì đó kỳ lạ sed.

Tôi thường xuyên cần chuyển đổi các tệp "giá trị được phân tách bằng tab" thành "giá trị được phân tách bằng dấu phẩy". Cách đơn giản nhất mà tôi biết là sử dụng sed, như thế này:

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

Điều này hoạt động hoàn hảo trên Linux: Nó thay thế mọi tab bằng dấu phẩy ... nhưng trên FreeBSD, nó không thay thế bất cứ điều gì !!!

Tui bỏ lỡ điều gì vậy? Có một cú pháp với FreeBSD khác với cú pháp sedtrên Linux không?

Câu trả lời:


9

Có lẽ bạn nên sử dụng -Etùy chọn (hoặc -rnhư được giải thích trong hướng dẫn ) để giữ khả năng tương thích với GNU Sed. Trong trường hợp của bạn, bạn có thể cài đặt Gnu Sed nếu bạn đã quen với nó (cổng gsed trên FreeBSD), hoặc sẽ mất nhiều thời gian để chuyển tập lệnh.

Và nhớ. Nếu một số lệnh trên BSD không hoạt động như phiên bản gnu của tiện ích đó, thì nó không có nghĩa là nó bị hỏng;)


1
Cảm ơn bạn. Các -Etùy chọn làm cho các trick (cả trên FreeBSD và trên Mac OS X).
Barranka

Trên FreeBSD 9 của tôi, tùy chọn -E không giúp được gì.
Ark-kun

6

Vâng, có nhiều sự khác biệt, hành vi-i là người duy nhất tôi biết ra khỏi đỉnh đầu.

Tôi chưa bao giờ sử dụng BSD vì vậy tôi thực sự không thể giúp với các chi tiết nhưng cách giải quyết khác có thể là sử dụng trthay thế:

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

Một tác dụng phụ dễ chịu là trnên nhanh hơn đáng kể. Tôi đã kiểm tra rằng trên Linux của tôi bằng cách sử dụng tệp thử nghiệm với 50000 dòng, mỗi dòng có 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

tr '\t' ,là di động hơn tr $'\t' ,. tr '[\t]' '[,]'thậm chí sẽ có thể di động đến một số hệ thống SysV cũ.
Stéphane Chazelas

tab là dấu phân cách mặc định cho cut. Thông số POSIX cho tr . Tôi đã sai về [cần thiết cho SysV cũ. Vì thông số kỹ thuật POSIX chỉ ra [chỉ cần cho các phạm vi ở đó.
Stéphane Chazelas

@StephaneChazelas là như vậy, xin lỗi không chắc chắn những gì tôi đang nhầm lẫn với nó sau đó. Cảm ơn đã làm rõ trong mọi trường hợp.
terdon

4

Có, không giống như GNU sedFreeBSD sedkhông diễn giải các chuỗi thoát ANSI C, như \ttrong các biểu thức thông thường.

Một cách để có được một bộ khử nhiễu ít phổ biến nhất trong trường hợp này là sử dụng printf.

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

Hành vi của các sed -ichỉnh sửa tệp tại chỗ có thể được thực hiện tương thích nếu một công tắc hoặc tùy chọn ngay sau công -itắc, ví dụ như sed -i -e 's/x/X/g' filehoạt động cho cả GNU sedcũng như FreeBSD sed.

Các phiên bản gần đây của FreeBSD sed(FreeBSD 8.1 trở lên) có công -rtắc để tăng khả năng tương thích với GNU sed.

(Ngoài ra, việc sử dụng các lớp ký tự POSIX trong sedcác biểu thức thông thường là một cách tốt để đảm bảo khả năng tương thích).

Để thay thế, sedtriển khai tuân thủ POSIX, xem: khai thác - triển khai SED nhỏ hơn, rẻ hơn, nhanh hơn .


3

Bạn nên sử dụng một TABký tự theo nghĩa đen thay vì \t:

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

Xem bình luận này của Stephane về một câu hỏi khác.

Bài viết sau đây cũng có thể bạn quan tâm:

Tôi trích dẫn phần có liên quan:

Sự khác biệt về Regex

Cú pháp biểu thức chính quy khác nhau một cách tinh tế giữa các phiên bản khác nhau của SED. Hầu hết các khác biệt liên quan đến các kiểu thoát đặc biệt được sử dụng để khớp với các ký tự không in, chẳng hạn như chuông ASCI và nguồn cấp dữ liệu mẫu.


0

Sau khi đăng nhập tôi thấy thông báo tiếp theo và lưu nó. Hy vọng nó cũng sẽ hữu ích cho người khác

Bạn muốn sử dụng sed (1) để chỉnh sửa một tập tin tại chỗ? Chà, để thay thế mọi 'e' bằng 'o', trong một tệp có tên 'foo', bạn có thể làm:

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

Và bạn sẽ nhận được bản sao lưu của bản gốc trong một tệp có tên 'foo.bak', nhưng nếu bạn không muốn sao lưu:

sed -i '' s/e/o/g foo

các -itùy chọn đã được bao phủ đã , mặc dù
Jeff Schaller
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.