Làm thế nào để tìm và thay thế chuỗi mà không sử dụng lệnh Sed?


16

Như chúng ta đã biết, sedrất hiệu quả để tìm và thay thế chuỗi, ví dụ: tìm 'a' và thay thế nó thành 'b' : sed 's/a/b/g'.

Có thể làm điều này với lệnh script hoặc shell khác thay vì sed?

Đây là một hệ thống linux bị cắt cho TV không có sedlệnh. Vì vậy, tôi phải sử dụng các lệnh hoặc tập lệnh khác thay vìsed 's/a/b/g'. –


Trên thực tế, đó chỉ là sự thay thế dựa trên biểu thức thông thường. Bất kỳ công cụ hoặc ngôn ngữ có khả năng để xử lý điều như vậy sẽ có thể làm như vậy, nhưng với cú pháp khác nhau: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Bên cạnh đó, nhiều công cụ và ngôn ngữ cũng có thể thực hiện thay thế chuỗi văn bản đơn giản. Vì vậy, câu hỏi của bạn là một số rộng.
manatwork

1
Tại sao? Vấn đề gì bạn đang cố gắng giải quyết?
Gilles 'SO- ngừng trở nên xấu xa'

Một hệ thống linux bị cắt cho TV không có lệnh sed. Vì vậy, tôi phải sử dụng lệnh hoặc tập lệnh khác để thay vì sed 's / a / b / g'.
binghenzq

Câu trả lời:


12

Có rất nhiều cách để làm điều này. Bạn có thể sử dụng awk, perlhoặc bashđể thực hiện các hoạt động này là tốt. Nhìn chung, sedcó lẽ là công cụ apropos nhất để thực hiện các loại nhiệm vụ này.

Ví dụ

Nói rằng tôi có dữ liệu mẫu này, trong một tệp data.txt:

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

ôi

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Chỉnh sửa nội tuyến

Các ví dụ trên có thể trực tiếp sửa đổi các tập tin quá. Ví dụ Perl là tầm thường. Đơn giản chỉ cần thêm công -itắc.

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Đối với awknó ít trực tiếp hơn nhưng cũng hiệu quả:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Phương thức này tạo một lớp vỏ con với dấu ngoặc nhọn '{...} `trong đó tệp được chuyển hướng vào nó thông qua điều này:

$ { ... } < data.txt

Khi tệp đã được chuyển hướng vào lớp vỏ phụ, nó sẽ bị xóa và sau đó awkđược chạy ngược lại với nội dung của tệp được đọc vào lớp vỏ phụ STDIN. Nội dung này sau đó được xử lý awkvà viết lại thành cùng tên tệp mà chúng ta vừa xóa, thay thế nó một cách hiệu quả.


Cảm ơn bạn đã trả lời và tôi sẽ thử nó vào ngày làm việc tiếp theo. Nhưng tôi không chắc nó có hoạt động không vì một số lệnh có thể không tồn tại trong một hệ thống linux bị cắt xén của TV, chẳng hạn như 'sed'.So tôi vẫn muốn sử dụng lệnh' find ' , 'grep' và như vậy để giải quyết nó.
binghenzq

@binghenzq - Tôi đã thêm các ví dụ chỉnh sửa nội tuyến tệp.
slm

-1 Tôi hiếm khi downvote nhưng trong trường hợp này, điểm của câu hỏi dường như là một phương pháp đơn giản hơn là khác / phức tạp hơn và có khả năng cũng phụ thuộc. Nếu câu hỏi chỉ là về các lựa chọn thay thế cho cài đặt máy * nix đầy đủ thì có lẽ tôi sẽ +1 câu trả lời tốt này.
Michael Durrant

@MichaelDurrant - Tôi vừa thêm những chỉnh sửa nội tuyến phức tạp b / c mà OP yêu cầu. Ngoài ra, OP đặt ra yêu cầu KHÔNG sử dụng sedkhông phải I. Sed là công cụ thích hợp để thực hiện các thay thế như thế này, và rõ ràng anh ta yêu cầu hiểu rõ hơn về vai trò của các công cụ này, vì vậy, cho mọi người thấy những điều này dù rất tệ, cực kỳ giáo dục họ tại sao. Quá nhiều lần các ppl trong biết chỉ đơn giản nói "đừng làm điều đó" mà không giải thích lý do tại sao, tôi cũng vậy. Nhưng cảm ơn vì ít nhất để lại một bình luận về lý do tại sao bạn DV.
slm

Chắc chắn, tôi nghĩ rằng đó là một câu trả lời tuyệt vời trong tất cả các khía cạnh khác. vâng tôi ghét -1 mà không có lời giải thích.
Michael Durrant

13

Thay thế cổ điển cho các thay thế một chữ cái là trlệnh nên có sẵn trên bất kỳ hệ thống nào:

$ echo "foobar" | tr a b   
foobbr

trsedthực sự tốt hơn cho việc này vì việc sử dụng sed(huống chi perlhoặc awk) cho việc thay thế một chữ cái cũng giống như sử dụng búa tạ để giết ruồi.

grep không được thiết kế cho việc này, nó không sửa đổi đầu vào của nó, nó chỉ tìm kiếm thông qua nó.

Ngoài ra, bạn có thể sử dụng khả năng thay thế của một số đạn pháo. Ở đây sử dụng ksh, zshhoặc bashcú pháp:

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Chúng tôi có thể cung cấp cho bạn câu trả lời cụ thể hơn nếu bạn giải thích chính xác vấn đề bạn đang cố gắng giải quyết.


Có một tùy chọn để bỏ qua trường hợp trong ${foo//a/b}?
AlikElzin-kilaka

@ AlikElzin-kilaka Tôi không sợ. Bạn sẽ phải sử dụng một cái gì đó tinh vi hơn, ví dụ: echo "$foo" | sed 's/a/b/ihoặc đưa ra một lớp nhân vật : echo ${foo//[aA]/b}.
terdon

4

Bạn có thể sử dụng Vim trong chế độ Ex:

ex -s -c '%s/a/b/g|x' file
  1. % chọn tất cả các dòng

  2. s thay thế

  3. g thay thế toàn cầu

  4. x lưu và đóng


cảm ơn rất nhiều. chỉ cần thêm, cờ -c là để thực thi lệnh khi bắt đầu chỉnh sửa (vì ex là trình chỉnh sửa) và cờ -s là chế độ tập lệnh vô hiệu hóa phản hồi hoặc như một số người muốn nói chế độ nghiêng. tham khảo để biết thêm thông tin: ex-vi.sourceforge.net/ex.html
Jimmy MG Lim

3

Nếu bạn đang làm việc với một tệp chứ không phải là một luồng, bạn có thể sử dụng trình soạn thảo văn bản tiêu chuẩn , ed:

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Điều này nên có sẵn trên bất kỳ * nix. Dấu phẩy ',s/a/b/g'cho biết edhoạt động trên mọi dòng (bạn cũng có thể sử dụng %, sẽ quen thuộc hơn nếu bạn đã sử dụng vim) và phần còn lại của nó là một tìm kiếm và thay thế tiêu chuẩn. wbảo nó ghi (lưu) tệp, qbảo nó thoát.

Lưu ý rằng, không giống như -itùy chọn của sed (và các tùy chọn tương tự trong các công cụ khác), điều này thực sự chỉnh sửa tệp tại chỗ thay vì gian lận với các tệp tạm thời.

Tôi không nghĩ rằng nó có thể làm việc này với các luồng, nhưng sau đó tôi không thực sự biết nhiều về nó edvà tôi sẽ không ngạc nhiên nếu nó thực sự có khả năng đó (triết lý unix là như vậy).


2

Sử dụng lệnh tổ tiên (có -snghĩa là yên lặng (im lặng) và dấu phẩy trước các lệnh có nghĩa là thực thi trên tất cả các dòng):

Chỉ cần in trên STDOUT :

ed -s file <<!
,s/a/b/g
,p
q
!

thay thế tại chỗ:

ed -s file <<!
,s/a/b/g
w
q
!
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.