Lệnh sed với tùy chọn -i bị lỗi trên Mac, nhưng hoạt động trên Linux


303

Tôi đã sử dụng thành công sedlệnh sau để tìm kiếm / thay thế văn bản trong Linux:

sed -i 's/old_link/new_link/g' *

Tuy nhiên, khi tôi dùng thử trên Mac OS X, tôi nhận được:

"lệnh c mong đợi \ theo sau là văn bản"

Tôi nghĩ máy Mac của tôi chạy vỏ BASH bình thường. Có chuyện gì vậy?

BIÊN TẬP:

Theo @High Performance, điều này là do Mac sedcó hương vị (BSD) khác, do đó, câu hỏi của tôi là làm thế nào để tôi sao chép lệnh này trong BSD sed?

BIÊN TẬP:

Đây là một ví dụ thực tế gây ra điều này:

sed -i 's/hello/gbye/g' *

1
Điều này có nghĩa là sedxem "c" trong dữ liệu của bạn dưới dạng lệnh. Bạn đang sử dụng một biến? Vui lòng gửi một cái gì đó đại diện chặt chẽ hơn cho lệnh thực tế và một số dữ liệu mà bạn đang xử lý. Bạn có thể có được một minh chứng đơn giản về lỗi này bằng cách làm echo x | sed c.
Tạm dừng cho đến khi có thông báo mới.

@Dennis, lệnh đơn giản ở trên gây ra điều này, mặc dù dữ liệu mà nó xử lý là toàn bộ trang web (tôi đang chuyển đổi tất cả các liên kết hình ảnh), bao gồm các tệp html và css ...
Yarin

Câu trả lời:


397

Nếu bạn sử dụng -itùy chọn, bạn cần cung cấp tiện ích mở rộng cho các bản sao lưu của mình.

Nếu bạn có:

File1.txt
File2.cfg

Lệnh (lưu ý việc thiếu không gian giữa -i''-eđể làm cho nó hoạt động trên các phiên bản mới của Mac và trên GNU):

sed -i'.original' -e 's/old_link/new_link/g' *

Tạo 2 tệp sao lưu như:

File1.txt.original
File2.cfg.original

Không có cách di động để tránh tạo các tệp sao lưu vì không thể tìm thấy hỗn hợp các lệnh sed hoạt động trong mọi trường hợp:

  • sed -i -e ...- không hoạt động trên OS X vì nó tạo -ebản sao lưu
  • sed -i'' -e ... - không hoạt động trên OS X 10.6 nhưng hoạt động trên 10.9+
  • sed -i '' -e ... - không hoạt động trên GNU

Lưu ý Cho rằng không có lệnh sed hoạt động trên tất cả các nền tảng, bạn có thể thử sử dụng một lệnh khác để đạt được kết quả tương tự.

Ví dụ, perl -i -pe's/old_link/new_link/g' *


4
Tôi gặp vấn đề tương tự. Cảm ơn giải pháp này. Nhưng nơi tôi đã cố gắng với 'man sed' để tìm mô tả về '-i', không có gì về việc sử dụng -i '' để bỏ qua các bản sao lưu ở đó. Đây là lỗi đầu tiên của tôi. Thứ hai, khi lỗi "lệnh mong đợi \ theo sau là văn bản" xuất hiện, tại sao nó không trực tiếp cho chúng ta biết rằng nó mong đợi một tên dự phòng cho tùy chọn '-i' !! ?? Điều đó xảy ra ở mọi nơi: bạn gặp lỗi nhưng không hiểu tại sao lại xảy ra lỗi, sau đó bạn tìm kiếm hướng dẫn không giải thích gì về nó. Sau đó, bạn google nó để tìm người khác cũng có vấn đề tương tự. Ý tôi là, tại sao không đưa ra ví dụ trong hướng dẫn?
lukmac

hoặc cho chúng tôi biết lý do tại sao có lỗi thay vì chỉ có một thông báo thiếu thông tin rằng có lỗi xảy ra. Đây là một gợi ý cho tất cả các nhà sản xuất công cụ, nếu họ có thể đọc bình luận này.
lukmac

5
@lukmac Theo như sedcó thể nói, bạn DID cung cấp hậu tố dự phòng. Hậu tố sao lưu là s/old_link/new_link/g. Đối số tiếp theo sau đó được cho là các lệnh chỉnh sửa. Bởi vì nó diễn giải các lệnh là tên sao lưu, sau đó nó lấy tên tệp đầu tiên làm các lệnh chỉnh sửa, nhưng chúng không hợp lệ.
Barmar

2
Điều này sẽ luôn luôn là một vấn đề? Có cách nào đó để Apple có thể tạo một giải pháp GNU sed giải pháp / gói với OSX không? Hoặc, không thể hỗ trợ GNU sed sed -i '' -e ...?
blong

5
sed -i'' -edường như không hoạt động như mong đợi trên mac 10.14
MoOx 6/12/18


55

Điều này hoạt động với cả hai phiên bản GNU và BSD của sed:

sed -i'' -e 's/old_link/new_link/g' *

hoặc với bản sao lưu:

sed -i'.bak' -e 's/old_link/new_link/g' *

Lưu ý thiếu không gian sau khi -itùy chọn! (Cần thiết cho GNU sed)


7
Cái đầu tiên không hoạt động trên OSX (Tôi vừa thử nó vào ngày 10.6.8)
marcin 11/11/13

4
Đối với tôi trên OS X (10.10.3), tệp sao lưu đầu tiên được tạo có hậu tố là -e. Không tốt. Cái thứ hai là thứ duy nhất hoạt động với tôi một cách nhất quán giữa Ubuntu và OS X. Mặc dù vậy, tôi không muốn các tệp sao lưu, vì vậy tôi phải chạy một rmlệnh ngay sau đó để xóa nó.
Brendan

1
Dòng đầu tiên nên được viết lại bằng một khoảng trắng để hoạt động vào ngày 10.10: sed -i'' ...=>sed -i '' ...
Daniel Jomphe

3
@DanielJomphe Nhưng việc thêm không gian này không hoạt động trên GNU sed
Brice

1
@marcin đầu tiên cũng hoạt động với tôi trên OSX 10.11.2. Chỉ có điều là nó tạo ra một tập tin sao lưu, cần phải được gỡ bỏ sau đó. Thứ hai có vẻ tốt hơn, vì chúng ta không phải tìm ra tên tệp sau này.
vikas027

41

Có cùng một vấn đề trong Mac và đã giải quyết nó bằng brew:

brew install gnu-sed

và sử dụng như

gsed SED_COMMAND

bạn có thể đặt cũng như đặt sedbí danh thành gsed(nếu bạn muốn):

alias sed=gsed

3
Tại sao bạn lại đưa ra câu trả lời chính xác như Ohad Kravchick ?
gniourf_gniourf

1
thiết lập bí danh như thế này không phải là một ý tưởng tuyệt vời
SantaXL

1
Thay vì bí danh, như được đề xuất trong trang bia tương ứng, hãy thêm nó vào đường dẫn: PATH = "$ (brew --prefix) / opt / gnu-sed / libexec / gnubin: $ PATH"
y.luis

24

Hoặc, bạn có thể cài đặt phiên bản GNU của sed trong máy Mac của mình, được gọi là gsed và sử dụng nó bằng cú pháp Linux tiêu chuẩn.

Vì thế, hãy cài đặt gsedbằng các cổng (nếu bạn không có nó, hãy lấy nó tại http://www.macports.org/ ) bằng cách chạy sudo port install gsed. Sau đó, bạn có thể chạysed -i 's/old_link/new_link/g' *


24
.. hoặc nếu bạn sử dụng homebrew, sau đó cài đặtgnu-sed
Sudar

1
Cảm ơn @Sudar, đôi ngón tay cái lên!
Andrew Swan

9

Máy Mac của bạn thực sự chạy shell BASH, nhưng đây là câu hỏi về việc triển khai sed mà bạn đang xử lý. Trên máy Mac sed đến từ BSD và khác biệt một chút so với máy sed bạn có thể tìm thấy trên một hộp Linux điển hình. Tôi đề nghị bạn man sed.


3
Cảm ơn bạn đã chỉ ra vấn đề BSD- Nhưng tôi khá mù chữ và chỉ cần sửa chữa nhanh chóng cho mệnh lệnh của mình - liếc nhanh vào người đàn ông không nói gì với tôi
Yarin

5
@Yarin - không, và nếu tôi lướt qua người đàn ông quyến rũ, điều đó cũng không cho bạn biết điều gì cả. Hãy thử nhìn thoáng qua.
Đánh dấu hiệu suất cao

21
Hầu hết các câu trả lời SO được chôn giấu ở đâu đó trong một người đàn ông, nhưng đó là những gì SO dành cho những người bận rộn, những người cần câu trả lời từ những người thông minh
Yarin

9

Câu trả lời của Sinetris là đúng, nhưng tôi sử dụng câu findlệnh này để cụ thể hơn về những tập tin tôi muốn thay đổi. Nói chung, điều này sẽ làm việc (thử nghiệm trên osx /bin/bash):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

Nói chung khi sử dụng sedmà không có findtrong các dự án phức tạp thì kém hiệu quả.


-execrất đẹp Tôi chỉ tự hỏi liệu dấu gạch chéo cuối cùng có thực sự cần hay không
Ye Liu

2
@YeLiu: không có \, cái ;vỏ được giải thích khi tôi thử như vậy
serv-inc

2

Tôi đã tạo một chức năng để xử lý sedsự khác biệt giữa MacOS (được thử nghiệm trên MacOS 10.12) và các HĐH khác:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

Sử dụng:

$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")

Ở đâu:

, là một đồng hồ đo

's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' là mô hình

"./mysql/.env" là đường dẫn đến tập tin


1

Dưới đây là cách áp dụng các biến môi trường cho tệp mẫu (không cần sao lưu).

1. Tạo mẫu bằng {{FOO}} để thay thế sau này.

echo "Hello {{FOO}}" > foo.conf.tmpl

2. Thay thế {{FOO}} bằng biến FOO và xuất ra tệp foo.conf mới

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Hoạt động cả macOS 10.12.4Ubuntu 14.04.5


0

Như các câu trả lời khác chỉ ra, không có cách nào để sử dụng sed một cách có thể di chuyển trên OS X và Linux mà không tạo các tệp sao lưu. Vì vậy, thay vào đó, tôi đã sử dụng Ruby one-liner này để làm như vậy:

ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

Trong trường hợp của tôi, tôi cần gọi nó từ một raketác vụ (nghĩa là bên trong tập lệnh Ruby), vì vậy tôi đã sử dụng mức trích dẫn bổ sung này:

sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}

-1
sed -ie 's/old_link/new_link/g' *

Hoạt động trên cả BSD & Linux


3
Điều này tạo ra trên linux một tên tệp khác có enối thêm
Brice

1
Bị hỏng, tốt hơn để loại bỏ nó.
sorin

Nó đang hoạt động trên Mac và Linux. Vấn đề với giải pháp này là gì?
Hồi giáo Azab

Không, nó không hoạt động trên Mac BSD Sed - nó sẽ tạo một bản sao lưu với 'e' được thêm vào tên tệp.
Jesper Grann Laursen
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.