Tôi nghĩ rằng những gì bạn đang tìm kiếm là sed
... đó là một s tream ed itor mà sẽ cho phép bạn làm thay thế trên cơ sở line-by-line.
Khi bạn giải thích, lệnh `cat named.local | Khu grep' mang đến cho bạn một sản lượng một chút như thế này:
zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {
Tôi đoán bạn muốn đầu ra được một cái gì đó như thế này, kể từ khi bạn nói rằng bạn cần văn bản trong dấu ngoặc kép:
"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"
Vì vậy, trên thực tế, từ mỗi dòng, chúng tôi chỉ muốn văn bản giữa các dấu ngoặc kép (bao gồm cả hai dấu ngoặc kép.)
Tôi không chắc bạn đã quen thuộc với Regular Expressions, nhưng chúng là một công cụ vô giá cho bất kỳ ai viết kịch bản shell. Ví dụ: biểu thức chính quy /.o.e/
sẽ khớp với bất kỳ dòng nào có từ thứ 2 có chữ cái viết thường là o
và số thứ 4 là e
. Điều này sẽ phù hợp với chuỗi có chứa những từ như "zone
", "tone
", hay thậm chí là "I am tone-deaf.
"
Bí quyết đã ở đó để sử dụng ký tự .
(dot) có nghĩa là "bất kỳ chữ". Có một vài ký tự đặc biệt khác, chẳng hạn như *
có nghĩa là "lặp lại ký tự trước đó 0 hoặc nhiều lần". Vì vậy, một biểu hiện thường xuyên như a*
sẽ phù hợp với "a
", "aaaaaaa
", hoặc một chuỗi rỗng: ""
Vì vậy, bạn có thể phù hợp với chuỗi bên trong dấu ngoặc kép sử dụng: /".*"/
Có một điều bạn sẽ biết về sed
(và theo nhận xét, bạn đã làm!) - nó cho phép backtracking. Một khi bạn đã nói với nó làm thế nào để nhận ra một từ, bạn có thể có nó sử dụng từ đó như là một phần của sự thay thế. Ví dụ, chúng ta hãy nói rằng bạn muốn chuyển danh sách này:
Billy "The Kid" Smith
Jimmy "The Fish" Stuart
Chuck "The Man" Norris
Into danh sách này:
The Kid
The Fish
The Man
Trước tiên, bạn muốn tìm kiếm chuỗi trong dấu ngoặc kép. Chúng tôi đã thấy rằng, đó là /".*"/
.
Tiếp theo, chúng tôi muốn sử dụng nội dung bên trong dấu ngoặc kép.Chúng ta có thể nhóm nó sử dụng dấu ngoặc: /"(.*)"/
Nếu chúng ta muốn thay thế các văn bản với các dấu ngoặc kép với một dấu gạch dưới, chúng tôi muốn làm một thay thế: s/"(.*)"/_/
, và điều đó sẽ để lại cho chúng ta:
Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris
Nhưng chúng tôi có backtracking! Điều đó sẽ cho phép chúng ta nhớ lại những gì nằm trong các parens, sử dụng ký hiệu \1
. Vì vậy, nếu chúng ta làm gì bây giờ: s/"(.*)"/\1/
chúng tôi sẽ nhận được:
Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris
Bởi vì có dấu ngoặc kép là không nằm trong dấu ngoặc, họ không phải là một phần của nội dung của \1
!
Để chỉ để nội dung bên trong dấu ngoặc kép, chúng tôi cần khớp toàn bộ dòng. (. Có nghĩa là "cuối dòng") để làm điều đó chúng tôi có ^
(có nghĩa là "sự khởi đầu của dòng"), và $
Vì vậy, bây giờ nếu chúng ta sử dụng s/^.*"(.*)".*$/\1/
, chúng tôi sẽ nhận được:
The Kid
The Fish
The Man
Tại sao? Hãy đọc các biểu thức chính quy s/^.*"(.*)".*$/\1/
từ trái sang phải:
Trong tiếng Anh đơn giản:. "Đọc toàn bộ dòng, sao chép sang một bên các văn bản giữa hai dấu ngoặc kép Sau đó, thay thế toàn bộ phù hợp với nội dung giữa các qoutes đôi."
Bạn thậm chí có thể thêm đúp quote xung quanh văn bản thay thế s/^.*"(.*)".*$/"\1"/
, vì vậy chúng tôi sẽ nhận được:
"The Kid"
"The Fish"
"The Man"
Và đó có thể được sử dụng bởi sed
để thay thế cho phù hợp với nội dung từ bên trong dấu ngoặc kép:
sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
(Đây chỉ là vỏ thoát để đối phó với hai dấu ngoặc kép và dấu gạch chéo và các công cụ.)
Vì vậy, toàn bộ lệnh wo uld có dạng như sau:
cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
Yup, tôi đang sử dụng nó ngay bây giờ, nhưng tôi nghĩ rằng nên có cách dễ dàng hơn để làm điều đó, bởi vì bây giờ tôi sử dụng sed-'s/zone "// g' | sed -e 's /" { // g 'để xóa đầu và cuối của một tệp thay vì chỉ khớp với phần giữa. – jpou
Cạo đầu và cuối là hoàn toàn chấp nhận được. Đây không phải là cuộc thi - nếu nó hoạt động, nó ổn. Nếu bạn muốn làm điều đó bằng cách kết hợp văn bản trong dấu ngoặc kép, hãy xem ‘chụp nhóm’. – zoul
ugh. Tôi đã dành quá nhiều thời gian để đánh máy, và nó vẫn chưa được thực hiện ... có vẻ như mọi người đã đánh tôi với nó. Nhưng tôi vui vì bạn đã tìm ra :-) – scraimer