test.xml文件很大,內容結構如下: list.txt文件較小,內容如下: 需求是,如果<url>...</url>中間包含了list.txt文件中的某一行,則刪除這個<url>...</url>。 在這裡需要說明下sed的局限性:(1).sed處理輸入流是一次性的,只要某行被sed讀取了,就一 ...
test.xml文件很大,內容結構如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<url>
<loc>http://www.u1cat.net/index.php?ctl=register</loc>
<lastmod>2016-10-31</lastmod>
<changefreq>always</changefreq>
<priority>aaa</priority>
</url>
<url>
<loc>http://www.u2bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>bbb</priority>
</url>
<url>
<loc>http://www.u3bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>ccc</priority>
</url>
<url>
<loc>http://www.u4bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>ddd</priority>
</url>
<url>
<loc>http://www.u5bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>ddd</priority>
</url>
......
list.txt文件較小,內容如下:
bbb
xxx
yyy
ccc
需求是,如果<url>...</url>
中間包含了list.txt文件中的某一行,則刪除這個<url>...</url>
。
在這裡需要說明下sed的局限性:
(1).sed處理輸入流是一次性的,只要某行被sed讀取了,就一定不會再讀取。因此,讀取到某滿足匹配要求的行時,無法定位到它前面的某行、某幾行。
(2).sed自身沒有顯式的迴圈結構,例如while、for、until。但是通過某些功能的結合,可以隱式地實現迴圈。據我總結,只有標簽跳轉和"NDP"才能實現這種隱式意義上的迴圈。
(3).sed和system命令交互的局限性非常大。只有e命令和s命令的e修飾符才能執行system中的命令。
正是這3個局限性,導致sed實現上面的需求非常困難。
以下是一種效率非常高的方法:只讀取一次test.xml和list.txt文件,併在每次讀取到<url>...</url>
的時候判斷是否需要刪除這一段。
創建sed腳本文件a.sed:
#!/usr/bin/sed -nf
\%<url>%!p
1{s/.*/cat list.txt/e;h}
\%<url>%{
N;N;N;N;N;G;
\%<priority>(.*)</priority>.*\1.*%d
}
s%</url>.*%</url>%p
執行sed:
sed -rn -f a.sed test.xml
由於上面示例文件中<priority>bbb</priority>
和<priority>ccc</priority>
的bbb、ccc存在於list.txt文件中,因此這兩個<url>...</url>
段落要刪除。執行結果為:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<url>
<loc>http://www.u1cat.net/index.php?ctl=register</loc>
<lastmod>2016-10-31</lastmod>
<changefreq>always</changefreq>
<priority>aaa</priority>
</url>
<url>
<loc>http://www.u4bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>ddd</priority>
</url>
<url>
<loc>http://www.u5bat.cc/index.php?ctl=register</loc>
<lastmod>2015-11-18</lastmod>
<changefreq>always</changefreq>
<priority>ddd</priority>
</url>
思路大致為:
- (1).一開始就通過sed的e命令將list.txt文件讀取到pattern space空間,並保存到hold space。
- (2).每讀取到的時候就繼續讀取後面5行,正好讀到。
- (3).讀完了後,把hold space中的內容追加回pattern space,並從XXXXX開始判斷後面是否還有XXXXX,如果有就直接刪除pattern space,否則就將追加回pattern space的list.txt內容刪除,最後輸出。
- (4).這樣的執行方式,只需讀取一次test.xml和list.txt文件,效率很高。
回到Linux系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到網站架構系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到資料庫系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/8849371.html
註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!