Shell 如何从其他文件中删除特定于文件的内容?

Shell 如何从其他文件中删除特定于文件的内容?,shell,sed,command,Shell,Sed,Command,我有一个foo.txt文件: $cat foo.txt <ul> <li> <p>something</p> </li> <li> <p>something else</p> </li> </ul> 但它不起作用,我也做不到: $sed '/<li>/,/</li>/ d' foo.txt $sed'//,//d'foo.txt 因为还有其他元素。

我有一个foo.txt文件:

$cat foo.txt

<ul>
<li>
<p>something</p>
</li>
<li>
<p>something else</p>
</li>
</ul>
但它不起作用,我也做不到:

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

    因为还有其他元素。

    这个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>
    
    kent$head foo bar
    
    ==>foobarsed是一个非常好的工具,用于在一条线上进行简单的替换,对于其他任何操作,请使用awk。以下是GNU awk解决方案:

    $ 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>
    
    $gawk-vrs='\0'-vrs='NR==FNR{re=$0;next}{sub(re,“”)}1'bar.txt foo.txt
    
    • 别的

    如果“bar.txt”可以包含RE元字符,并且您发现这些元字符会在sub()中导致不需要的匹配(匹配大量文本时不太可能),那么您需要切换到index()+substr()的解决方案来处理字符串而不是REs,例如:

    $ 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>
    
    $gawk-vrs='\0'-vrs='
    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
    
    • 别的


    在sed中,r命令将文件读入输出流,而不是作为脚本的一部分。您使用
    sed-f脚本加载脚本…
    ,但这不起作用,因为bar.txt不是有效的sed脚本。要将bar.txt转换为有效的sed命令,您需要一个中间步骤。不幸的是,它不起作用。标记(常规HTML)之间有许多换行符和空格,虽然我用\n+-替换了\n,但没有帮助…
    \n+
    是错误的。空格和多重
    \n
    不是问题。若你们有空行,这可能是个问题。我在回答中提到。您可以使用awk中的sprintf函数来解决空行问题。我当前的代码适用于您的示例。它们都不起作用:(可能“bar.txt”太复杂了?:
  • 标题某物



    某物
  • (它跨越多行)“它们都不起作用"不会帮助我们解决问题,因为它不会告诉我们问题是什么。在评论中发布一堆HTML也不会有帮助。如果您的输入文件看起来像您在问题中发布的示例输入,则我发布的脚本肯定会工作。如果您的真实输入看起来不像示例输入,那么脚本当然不会工作。不是吗在您的输入文件上运行
    cat-v
    ,查看行的末尾是否有控件Ms,如果您在Windows上创建了输入文件就会发生这种情况。@user2275835-“to_remove”的内容与“index.html”的内容不匹配?后者在以“”开头的行和行末尾的文本与2完全不同。我将发布2并突出显示差异。哦,我的天哪……因为错误的文本选择浪费了太多时间……非常感谢你,Ed!@user2275835如果你有满意的答案,不要忘了点击答案旁边的复选标记,这样其他海报就不会浪费时间了他们需要拿出不同的答案。
    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>
    
    $ 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>
    
    $ 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>