#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 sedkhô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 look. Sau đó bạn có thể giải quyết các \nký tự.
sed l <file
Sẽ cho bạn thấy mỗi dòng sedxử 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 \backslashsau ,commatrong 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 pcho một lvì 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<<\SCRIPTchỉ 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 look 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 lvà 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à Hkhô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ỏ look 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 Hkhô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>$
Hkhô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ỉ xthay đổ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 dbở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ự Hnhư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 sedkịch bản.