6

假设我有以下类型的文件:

<?xml version="1.0" encoding="utf-8"?>
<preferences>
  <section id="widgets">
    <value id="version" xml:space="preserve">1</value>
  </section>
  <section id="wuid-b2a8e6b8-6619-714e-9cfe-466c27c90902">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/opera-adblock-1.3.4-1.oex</value>
  </section>
  <section id="wuid-0c5cfdb2-8e51-f149-a1e7-51d66240ed7a">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/flag-button-1.5.4-1.oex</value>
  </section>
</preferences>

我的任务是在最后一次出现</section>.

看看这两个,似乎利用tac会更简单,但我也不明白如何做到这一点:使用 sed 将字符串附加到模式的第四次出现http://www.unix.com/unix- dummies-questions-answers/46294-add-line-after-last-occurnace-pattern.html#post302149709

谢谢。

4

7 回答 7

6

这可能对您有用(GNU sed):

sed '/\/section/{x;/./p;x;h;d};x;/./!{x;b};x;H;$!d;x;s/\/section[^\n]*\n/&  HELLO\n/' file

本质上:遇到包含/section开始将所有剩余行存储到文件末尾的保留空间(HS)中的行。如果行已经在保持空间中并且遇到另一个这样的行,则打印 HS 中的行并再次开始存储行。在文件末尾插入所需的字符串并打印出存储的行。

于 2013-02-12T06:55:01.453 回答
2

在最后一个section标签之后插入文本,即在结束“preferences”标签之前:

sed 's#</preferences>#  HELLO\n&#' file.xml

输出如下所示:

...
  </section>
  HELLO
</preferences>

要做到这一点,请使用-i标志:

sed -i 's#</preferences>#  HELLO\n&#' file.xml

做一个管道:

cat file.xml | ...whatever... | sed 's#</preferences>#  HELLO\n&#'

注意,在 XML上使用sed和正则表达式往往会导致问题,因为 XML 既不是基于正则表达式也不是基于行。为了做得更好,请在 perl、python、ruby、java 等中使用真正的 XML 解析器。

于 2013-02-11T00:14:00.677 回答
2

单程 :

sed -i 's@</preferences>@  <section id="x">\n   <value id="path to widget data" xml:space="preserve">{Preferences}widgets/xxxx</value>\n  </section>\n&@' file.xml

这个片段<section>XML文件中添加了一个新的。

结果

<?xml version="1.0" encoding="utf-8"?>
<preferences>
  <section id="widgets">
    <value id="version" xml:space="preserve">1</value>
  </section>
  <section id="wuid-b2a8e6b8-6619-714e-9cfe-466c27c90902">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/opera-adblock-1.3.4-1.oex</value>
  </section>
  <section id="wuid-0c5cfdb2-8e51-f149-a1e7-51d66240ed7a">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/flag-button-1.5.4-1.oex</value>
  </section>
  <section id="x">
   <value id="path to widget data" xml:space="preserve">{Preferences}widgets/xxxx</value>
  </section>
</preferences>
于 2013-02-11T00:16:45.543 回答
2

在第一次出现字符串之前添加内容更容易:

sed '/<\/preferences>/i\ADD SOME TEXT\nADD SOME MORE TEXT' file

结果:

<?xml version="1.0" encoding="utf-8"?>
<preferences>
  <section id="widgets">
    <value id="version" xml:space="preserve">1</value>
  </section>
  <section id="wuid-b2a8e6b8-6619-714e-9cfe-466c27c90902">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/opera-adblock-1.3.4-1.oex</value>
  </section>
  <section id="wuid-0c5cfdb2-8e51-f149-a1e7-51d66240ed7a">
    <value id="path to widget data" xml:space="preserve">{Preferences}widgets/flag-button-1.5.4-1.oex</value>
  </section>
    ADD SOME TEXT
    ADD SOME MORE TEXT
</preferences>

您可以在此处阅读有关如何在字符串前插入一行的更多信息。HTH。

于 2013-02-11T00:22:59.953 回答
1

使用 awk 你可以这样做

awk '$0 ~ /<\/pref/{print "Hello\n"$0}' temp.txt

输出

Hello
</preferences>
于 2013-02-11T02:20:44.083 回答
1

@Steve上面的答案是解决这个问题的正确方法,但它包含一个导致它在 OS X 上失败的怪癖。编码多行插入sed脚本的正确、可移植的方法是:

  1. 在实际内容之前加上换行符,
  2. 使用反斜杠转义每个换行符(包括命令后的第一个换行符)。

鉴于您最初帖子中的文字,这是一个更新的示例:

sed -i '' '/<\/preferences>/i\
ADD SOME TEXT\
ADD SOME MORE TEXT\
' test.xml

作为参考,摘自OS Xsed(1)手册页

     [2addr]H
             Append a newline character followed by the contents of the pattern space to the hold space.

     [1addr]i\
     text    Write text to the standard output.

     [2addr]l
             (The letter ell.)  Write the pattern space to the standard output in a visually unambiguous

……并来自GNUsed(1)手册页

       text   Append text, which has each embedded newline preceded by a back-
          slash.

       i \

       text   Insert text, which has each embedded newline preceded by a back-
          slash.

       q      Immediately  quit  the  sed  script  without processing any more
          input, except that if auto-print is  not  disabled  the  current
于 2015-01-07T16:48:21.260 回答
0

这是我要在 last 之后添加一行时的方法#include

grep -n '#include' $file | tail -1 | cut -f1 -d: | xargs -I % echo %+1 | bc | 
xargs -I '{}' sed -i '{}i// clang-format off' $file
  • 获取最后一次出现的行号并将其加 1。
  • 使用 sed 在该行插入一行。
于 2019-09-05T08:15:14.530 回答