從a文件判斷是否刪除b文件中的行(sed示例)

bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.htmlphp


test.xml文件很大,內容結構以下:html

<?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文件較小,內容以下:shell

bbb
xxx
yyy
ccc

需求是,若是<url>...</url>中間包含了list.txt文件中的某一行,則刪除這個<url>...</url>bash

在這裏須要說明下sed的侷限性:
(1).sed處理輸入流是一次性的,只要某行被sed讀取了,就必定不會再讀取。所以,讀取到某知足匹配要求的行時,沒法定位到它前面的某行、某幾行。
(2).sed自身沒有顯式的循環結構,例如while、for、until。可是經過某些功能的結合,能夠隱式地實現循環。據我總結,只有標籤跳轉和"NDP"才能實現這種隱式意義上的循環。
(3).sed和system命令交互的侷限性很是大。只有e命令和s命令的e修飾符才能執行system中的命令。
正是這3個侷限性,致使sed實現上面的需求很是困難。url

如下是一種效率很是高的方法:只讀取一次test.xml和list.txt文件,並在每次讀取到<url>...</url>的時候判斷是否須要刪除這一段。spa

建立sed腳本文件a.sed:.net

#!/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:code

sed -rn -f a.sed test.xml

因爲上面示例文件中<priority>bbb</priority><priority>ccc</priority>的bbb、ccc存在於list.txt文件中,所以這兩個<url>...</url>段落要刪除。執行結果爲:regexp

<?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>

思路大體爲:xml

  • (1).一開始就經過sed的e命令將list.txt文件讀取到pattern space空間,並保存到hold space。
  • (2).每讀取到<url>的時候就繼續讀取後面5行,正好讀到</url>。
  • (3).讀完了後,把hold space中的內容追加回pattern space,並從XXXXX開始判斷後面是否還有XXXXX,若是有就直接刪除pattern space,不然就將追加回pattern space的list.txt內容刪除,最後輸出。
  • (4).這樣的執行方式,只需讀取一次test.xml和list.txt文件,效率很高。
相關文章
相關標籤/搜索