Tại sao `sed` không trả về trạng thái thoát nếu regex không khớp?


8

Tôi đang cố gắng tìm kiếm và thay thế một số dòng từ các tệp, nhưng khi tôi chạy sednếu regex đó không khớp thì sedkhông trả về bất kỳ mã trạng thái nào, vì vậy thay vì thêm một điều kiện nữa grep, có cách nào sedvà tại sao sedkhông trả lại trạng thái thoát ?

Vấn đề :

nhập mô tả hình ảnh ở đây


1
Điều đó đã được trả lời trên StackOverflow, stackoverflow.com/questions/15965073/
triệt

1
@DravSloan - Bạn có thể sao chép một số câu trả lời ở đây, đi tìm nó.
slm

Câu trả lời:


15

sed không trả về trạng thái thoát:

$ echo "foo" | sed 's/xx/yy/'
foo
$ echo $?
0
$ sed 's/xx/yy/' foo.txt
sed: can't read foo.txt: No such file or directory
$ echo $?
2

Mã thoát của Sed là về việc chương trình đã thoát thành công hay chưa, chúng không liên quan gì đến nội bộ của những gì sedđang làm, chỉ là liệu lệnh có được quản lý để chạy hay không.

Điều đó nói rằng, GNU sed cung cấp một cách để làm điều này:

   q [exit-code]
          Immediately  quit  the sed script without pro‐
          cessing any more input, except that  if  auto-
          print  is  not  disabled  the  current pattern
          space will be printed.  The exit code argument
          is a GNU extension.

Ví dụ (lấy từ đây ):

$  echo "foo"|sed '/foo/ s/f/b/;q'                                                                       
boo
$  echo $?
0
$ echo "trash"|sed  '/foo/{s/f/b/;q}; /foo/!{q100}'
trash
$  echo $?
100

Nếu bạn muốn báo cáo thực tế rằng bất kỳ sự thay thế nào đã thành công trên bất kỳ dòng nào của đầu vào, bạn có thể gắn cờ thay thế thành công trong không gian giữ và kiểm tra nó trên dòng cuối cùng:

seq 6 | sed 's/4/four/;s/5/five/; tm;${x;/1/{x;q};x;q1};b;:m;x;s/.*/1/;x'

tmcác chi nhánh để mnhãn nếu bất kỳ thay thế đã thành công. Ở đó, chúng tôi đặt 1trong không gian giữ, mà chúng tôi tìm kiếm trên dòng cuối cùng.


Mã thoát của egrep cung cấp thông tin về lệnh đang thực hiện, do đó không cần phải làm như vậy.
JohnyTex

@JohnyTex không ai nói nó phải. Tuy nhiên, grepkhông phải là một sự tương tự tốt. Grep là một chương trình đơn giản chỉ có thể làm một việc: tìm kiếm các mẫu. Vì vậy, chắc chắn, nếu nó không tìm thấy nó, nó có thể cho bạn biết. Tuy nhiên, sedlà một cái gì đó hoàn toàn khác và phức tạp hơn nhiều. Về cơ bản, nó là một ngôn ngữ kịch bản và bạn có thể sử dụng nó để thực hiện các tác vụ tùy ý. Có thể không có cách nào để biết liệu nó có "thành công" hay không vì thành công sẽ phụ thuộc vào chi tiết của tập lệnh bạn đang chạy. Do đó, giống như trong tất cả các ngôn ngữ lập trình, tùy thuộc vào lập trình viên để xác định trạng thái thoát.
terdon

"Mã thoát là về việc một chương trình đã thoát thành công hay chưa ..." dường như ngụ ý rằng chúng không thể có bất kỳ chức năng nào khác mặc dù ... Có lẽ chỉ cần làm rõ một chút.
JohnyTex

@JohnyTex Tôi đang nói đến mã thoát của sed, không phải mã thoát nói chung. Những gì mã thoát của chương trình thực hiện hoàn toàn phụ thuộc vào lập trình viên đã viết nó.
terdon

Tôi hiểu điều đó. Tôi chỉ nghĩ rằng phrasing là một chút đáng tiếc, mặc dù tôi thực sự không quan tâm đến điều đó thực sự nhiều.
JohnyTex

6

Đầu tiên, tất cả các lệnh, bao gồm sed, trả về trạng thái thoát. Bạn đang tìm kiếm lý do tại sao tôi sẽ không trở lại một thất bại. Điều đó dẫn đến điểm thứ hai.

Các chương trình như sedlà biên tập viên, không phải là vị ngữ. Họ ở đó để thay đổi dữ liệu chảy qua chương trình. Các điều kiện lỗi dành cho các điều kiện như các lệnh nội bộ không hợp lệ hoặc tệp không tồn tại trên dòng lệnh.

Tôi không chắc chắn về logic bạn muốn - bạn không bao gồm bất kỳ đầu ra dự kiến ​​nào - nhưng đây có thể là những gì bạn đang tìm kiếm:

$ sed '/^test line 7/s//#test line 7/;/^#test line 7/s//& \nAppend New Line/' test.txt
test line 1
test line 2
test line 3
test line 4
test line 5
test line 6
#test line 7
Append New Line

Có các cấu trúc khác cũng có thể xử lý việc này, ví dụ lệnh b(nhánh) trong sed.

Nếu bạn muốn một mã trả lại thực tế nếu không tìm thấy, thì bạn có thể muốn xem gawkexittuyên bố của nó .


Tuy nhiên, nó vẫn tiếp tục nối tiếp nếu chúng ta chạy đi chạy lại ..
Rahul Patil

Tôi đã giải quyết bằng grep, nhưng muốn biết trong sed .. github.com/rahulinux/bash-fifts-/blob/master/ mẹo
Rahul Patil

Bạn muốn chạy câu lệnh thứ hai chỉ khi câu lệnh đầu tiên thành công? Bạn có thể thêm lệnh mở rộng GNU T, giữa hai:sed -i '/^test line 7/s//#&/;T;/#test line 7/&\nAppend New Line/' test.txt
Arcege
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.