#begin command block
#append all lines between two addresses to hold space
sed -n -f - <<\SCRIPT file.xml
\|<tag1>|,\|</tag1>|{ H
#at last line of search block exchange hold and pattern space
\|</tag1>|{ x
#if not conditional ; clear buffer ; branch to script end
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
#do work ; print result; clear buffer ; close blocks
s?*?*?;p;s/.*//;h;b}}
SCRIPT
Nếu bạn làm như trên, với dữ liệu bạn hiển thị, trước dòng dọn dẹp cuối cùng ở đó, bạn sẽ làm việc với một sed
không gian mẫu trông giống như:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Bạn có thể in ra không gian mẫu của bạn bất cứ khi nào bạn muốn với l
ook. Sau đó bạn có thể giải quyết các \n
ký tự.
sed l <file
Sẽ cho bạn thấy mỗi dòng sed
xử lý nó ở giai đoạn l
được gọi.
Vì vậy, tôi vừa thử nghiệm nó và nó cần thêm một \backslash
sau ,comma
trong dòng đầu tiên, nhưng nếu không làm việc như là. Ở đây tôi đặt nó vào _sed_function
để tôi có thể dễ dàng gọi nó cho mục đích trình diễn trong suốt câu trả lời này: (hoạt động với các bình luận được đưa vào, nhưng ở đây bị xóa vì lý do ngắn gọn)
_sed_function() { sed -n -f /dev/fd/3
} 3<<\SCRIPT <<\FILE
\|<tag1>|,\|</tag1>|{ H
\|</tag1>|{ x
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
s?*?*?;p;s/.*//;h;b}}
#END
SCRIPT
<tag1>
<tag2>bar</tag2>
</tag1>
<tag1>
<tag2>foo</tag2>
</tag1>
FILE
_sed_function
#OUTPUT#
<tag1>
<tag2>foo</tag2>
</tag1>
Bây giờ chúng ta sẽ chuyển p
cho một l
vì vậy chúng tôi có thể xem những gì chúng tôi đang làm việc với khi chúng ta phát triển kịch bản của chúng tôi và loại bỏ các bản demo không-op s?
nên dòng cuối cùng của chúng tôi sed 3<<\SCRIPT
chỉ trông giống như:
l;s/.*//;h;b}}
Sau đó, tôi sẽ chạy lại:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
Đồng ý! Vì vậy, tôi đã đúng - đó là một cảm giác tốt. Bây giờ, hãy xáo trộn l
ook của chúng tôi để xem các dòng nó kéo vào nhưng xóa. Chúng tôi sẽ xóa hiện tại của chúng tôi l
và thêm một cái !{block}
để nó trông giống như:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Đó là những gì nó trông giống như trước khi chúng tôi xóa sạch nó.
Một điều cuối cùng tôi muốn cho bạn thấy là H
không gian cũ khi chúng tôi xây dựng nó. Có một vài khái niệm chính tôi hy vọng tôi có thể chứng minh. Vì vậy, tôi loại bỏ l
ook cuối cùng một lần nữa và thay đổi dòng đầu tiên để thêm một cái nhìn vào H
không gian cũ ở cuối:
{ H ; x ; l ; x
_sed_function
#OUTPUT#
\n<tag1>$
\n<tag1>\n <tag2>bar</tag2>$
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
\n<tag1>$
\n<tag1>\n <tag2>foo</tag2>$
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
H
không gian cũ tồn tại chu kỳ dòng - do đó tên. Vì vậy, những gì mọi người thường gặp phải - ok, những gì tôi thường gặp phải - là nó cần xóa sau khi bạn sử dụng nó. Trong trường hợp này tôi chỉ x
thay đổi một lần, vì vậy không gian giữ trở thành không gian mẫu và ngược lại và thay đổi này cũng tồn tại theo chu kỳ dòng.
Hiệu quả là tôi cần xóa không gian giữ của mình, nơi từng là không gian mẫu của tôi. Tôi làm điều này bằng cách trước tiên xóa không gian mẫu hiện tại với:
s/.*//
Mà chỉ cần chọn mỗi ký tự và loại bỏ nó. Tôi không thể sử dụng d
bởi vì điều này sẽ kết thúc chu kỳ dòng hiện tại của tôi và lệnh tiếp theo sẽ không hoàn thành, điều này sẽ làm hỏng khá nhiều kịch bản của tôi.
h
Điều này hoạt động theo cách tương tự H
nhưng nó ghi đè lên không gian, vì vậy tôi vừa sao chép không gian mẫu trống của mình lên trên không gian giữ của tôi, xóa nó một cách hiệu quả. Bây giờ tôi chỉ có thể:
b
ngoài.
Và đó là cách tôi viết sed
kịch bản.