it-swarm-vi.com

Sự khác nhau giữa sed trên Mac OSX và sed "tiêu chuẩn" khác?

Tôi đang gặp một số vấn đề khi sử dụng câu trả lời được cung cấp trên trang web này cho câu hỏi này về lệnh sed để thay thế một dòng trống bằng hai dòng nội dung khác , và nó đã được đưa lên nếu lệnh sed trên Mac HĐH (10.6.7 đối với tôi) thì khác. Tôi không nghĩ rằng nó là như vậy, nhưng đã tự hỏi nếu những người khác trên trang web này nghĩ khác.

67
Peter Grill

Hành vi của các tiện ích Shell khác nhau theo những cách nhỏ giữa các biến thể unix. Có nhiều biến thể nix , với một phức tạphistory . Có nỗ lực tiêu chuẩn hóa chẳng hạn như POSIX tiêu chuẩn và siêu thay thế của nó đặc tả UNIX đơn . Hầu hết các hệ thống hiện nay đều triển khai POSIX: 2001, còn được gọi là Phiên bản đặc tả UNIX đơn , với độ lệch nhỏ và nhiều phần mở rộng. Đặc tả Unix đơn không phải là một hướng dẫn, nhưng phiên bản 3 có thể đọc được nếu bạn đã có ý tưởng về những gì một lệnh đang làm. Bạn có thể tham khảo nó để biết liệu một số tính năng là tiêu chuẩn hoặc một phần mở rộng của một hệ thống cụ thể.

Phần lớn người dùng unix sử dụng Linux và chưa sử dụng bất kỳ biến thể nào khác. Linux đi kèm với GNU tiện ích, thường có nhiều tiện ích mở rộng theo tiêu chuẩn. Vì vậy, bạn sẽ tìm thấy khá nhiều mã ngoài đó hoạt động trên Linux nhưng không phải trên các thông báo khác, vì nó phụ thuộc vào các tiện ích mở rộng đó.

Về sed, hãy tham khảo đặc tả kỹ thuật Unix đơn với mức tối thiểu mà mọi hệ thống được cho là hỗ trợ, trang man trên hệ thống của bạn để biết những gì triển khai của bạn hỗ trợ và - Hướng dẫn sử dụng GNU sed cho những gì hầu hết mọi người sử dụng.

Một trong những phần mở rộng không chuẩn trong GNU sed đang hỗ trợ nhiều lệnh chạy cùng nhau. Ví dụ: chương trình sed GNU sed này in tất cả các dòng có chứa a, nhưng thay đổi b thành c trước tiên:

sed -ne '/a/ {s/b/c/g; p}'

{} Thực sự là các lệnh riêng biệt, vì vậy để có tính di động đầy đủ, bạn cần chỉ định chúng trên các dòng riêng biệt (trong một tệp) hoặc trong các đối số -e Riêng biệt (trên dòng lệnh). Việc thiếu dấu phân cách lệnh sau { Và việc sử dụng ; Làm dấu tách lệnh là các phần mở rộng phổ biến. Việc thiếu dấu phân cách lệnh trước } Là một phần mở rộng ít phổ biến hơn. Đây là tiêu chuẩn tuân thủ:

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

Điều này là không chuẩn nhưng thường được chấp nhận:

sed -ne '/a/ { s/b/c/g; p; }'

Một tiện ích mở rộng không chuẩn nhưng phổ biến khác là việc sử dụng \n Có nghĩa là một dòng mới trong văn bản thay thế s (việc sử dụng trong biểu thức chính quy là tiêu chuẩn). Phương thức di động là bao gồm dấu gạch chéo ngược mới trong tập lệnh sed. Một tiện ích mở rộng phổ biến khác là \+, \?\| Trong regexps có nghĩa là một hoặc nhiều, nhiều nhất là một và xen kẽ; biểu thức chính quy cơ bản di động không có cái nào trong số này. Ví dụ, lệnh đầu tiên là một cách không di động để thay thế các chuỗi liền kề của khoảng trắng bằng một dòng mới; lệnh thứ hai là tương đương tuân thủ tiêu chuẩn.

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'

OS X hiện đi kèm với một sed FreeBSD từ năm 2005. Hầu hết các khác biệt dưới đây cũng áp dụng cho các phiên bản sed BSD khác.

Sed X của OS X sử dụng -E cho ERE và GNU sed sử dụng -r. -E là bí danh cho -r in GNU sed (được thêm vào 4.2, không được ghi lại cho đến 4.3). Các phiên bản mới hơn của FreeBSD và NetBSD sed hỗ trợ cả -E-r. OpenBSD sed chỉ hỗ trợ -E.

-i '' hoạt động với sed của OS X nhưng không GNU sed. -i hoạt động với GNU sed, các phiên bản gần đây của NetBSD, OpenBSD sed, nhưng không phải là sed của OS X. -i -e hoạt động với cả hai nhưng trong trường hợp FreeBSD sed tạo bản sao lưu của tệp gốc với -e được thêm vào tên tệp (và bạn cần chuyển không quá một biểu thức cho sed).

GNU sed diễn giải các chuỗi thoát như \t, \n, \001, \x01, \w\b. Sed của OS X và sed POSIX chỉ diễn giải \n (nhưng không nằm trong phần thay thế của s).

GNU sed phiên dịch \|, \+\? trong BRE nhưng sed của OS X và sed POSIX thì không. \(, \), \{\} là BREIX BRE.

GNU sed cho phép bỏ qua ; hoặc một dòng mới trước } nhưng sed của OS X thì không.

i (insert), a (nối thêm) và c (thay đổi) phải được theo sau bởi dấu gạch chéo ngược và dòng mới trong sed của POS X và sedIX POS GNU sed. GNU sed thêm một dòng mới bị thiếu sau khi văn bản được chèn bởi i, a hoặc c nhưng sed của OS X thì không. Ví dụ sed 1ia là một GNU thay thế cho sed $'1i\\\na\n'.

Ví dụ printf a|sed -n p thêm một dòng mới trong sed của OS X nhưng không có trong GNU sed.

Sed X của OS X không hỗ trợ các bộ sửa đổi I (không phân biệt chữ hoa chữ thường) hoặc M (nhiều dòng). Các phiên bản mới hơn của FreeBSD sed hỗ trợ I.

Sed X của OS X không hỗ trợ -s (--separate), -u (--unbuffered), hoặc là -z (--null-data).

Một tùy chọn BSD không được hỗ trợ bởi GNU sed là -a, làm cho w chắp thêm vào một tệp thay vì cắt bớt một tệp.

Ví dụ về các lệnh GNU sed không hoạt động với sed của OS X:

sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a Shell command
sed -n l0 # 0 disables wrapping
69
Lri

Cách tốt nhất mà tôi đã tìm thấy để có cùng một kịch bản hoạt động trên cả Linux và Mac là:

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"
6
vikrantt