2

我有一个文件 foo.txt:

$cat foo.txt

<ul>
<li>
<p>something</p>
</li>
<li>
<p>something else</p>
</li>
</ul>

还有一个 bar.txt:

$cat bar.txt

<li>
<p>something</p>
</li>

我想要所需的输出:

<ul>
<li>
<p>something else</p>
</li>
</ul>

我努力了:

$sed '{/r bar.txt/} d' foo.txt

但它没有用,我不能这样做:

$sed '/<li>/,/</li>/ d' foo.txt

因为还有其他元素。

4

2 回答 2

1

此 awk 单行代码适用于您的示例:

 awk -v RS="" '{gsub(/\n/,"\x99")}NR==FNR{t=$0;next}{gsub(t,"");gsub(/\x99/,"\n");print}' bar foo

不完全相同的输出(空行),但你明白了。请参阅示例下方的简短说明。

请参见下面的示例:

kent$  head foo bar
==> foo <==
<ul>
<li>
<p>something</p>
</li>
<li>
<p>something else</p>
</li>
</ul>

==> bar <==
<li>
<p>something</p>
</li>

kent$  awk -v RS="" '{gsub(/\n/,"\x99")}NR==FNR{t=$0;next}{gsub(t,"");gsub(/\x99/,"\n");print}' bar foo
<ul>

<li>
<p>something else</p>
</li>
</ul>

添加简短说明

基本思想是,用不可见的字符替换换行符(在我使用的示例中\x99),然后我们有两个单行字符串。我们可以进行匹配和替换。在我们处理完字符串后,将所有字符串全部替换\x99回换行符以获取原始格式。这个想法也适用于 sed,但有点复杂,你必须制作一个标签并使用模式/保持空间......

在我刚刚使用的示例中RS=""(我有点懒)。您可以使用sprintf函数来构建单行字符串,它会更通用,因为您的两个真实文件都可能有空行。(但是你的例子没有)

关键是看不见的字符替换部分。

祝你好运!

于 2013-04-12T20:32:46.570 回答
1

sed is an excellent tool for simple subsitutions on a single line, for anything else use awk. Here is a GNU awk solution:

$ gawk -v RS='\0' -v ORS= 'NR==FNR{re=$0;next} {sub(re,"")} 1' bar.txt foo.txt
<ul>
<li>
<p>something else</p>
</li>
</ul>

If "bar.txt" can contain RE metacharacters and you find those causing undesirable matches in the sub() (unlikely when matching large amounts of text) then you need to switch to an index()+substr()s solution to work with strings instead of REs, e.g.:

$ gawk -v RS='\0' -v ORS= '
   NR==FNR { str=$0; rlength=length(str); next }
   rstart = index($0,str) { $0 = substr($0,1,rstart-1) substr($0,rstart+rlength) }
   1' bar.txt foo.txt
<ul>
<li>
<p>something else</p>
</li>
</ul>
于 2013-04-13T17:12:38.827 回答