sed查找正则表达式模式,然后查找下一个正则表达式模式(变量多行)并替换



我正试图找到一种方法,使用sed将字符串".sh"插入到文本文件中的特定行中。我遇到的问题是,我只想在以前的regex匹配的情况下插入字符串,它还必须支持"name"one_answers"extension"标记之间的可变行数,并且是幂等的,所以我可以多次运行它,只需为"extension'"标记的空格分隔列表插入一个".sh"。

以下是文本文件的一小段:-

<name>gba</name>
<fullname>Game Boy Advance</fullname>
<manufacturer>Nintendo</manufacturer>
<release>2001</release>
<hardware>portable</hardware>
<path>/storage/roms/gba</path>
<extension>.gba .GBA .zip .ZIP .7z .7Z</extension>

所以我只想在名称标签是<name>gba</name>的情况下将<extension>.gba .GBA .zip .ZIP .7z .7Z</extension>更改为<extension>.gba .GBA .zip .ZIP .7z .7Z .sh</extension>

这是我迄今为止想出的最好的一个,但它有两个问题,首先是代码的后续执行重复了插入,其次是针对固定数量的行(6(,可能并不总是这样:-

sed -i '/<name>gba</name>/{n;n;n;n;n;n;s/</extension>/ .sh</extension>/}' /tmp/test.txt

GNU sed测试(语法可能因其他实现而异(:

sed '/<name>gba</,/<extension>/{/<extension>/{/.sh/! s/</extension>/ .sh&/}}'
  • /<name>gba</,/<extension>/这将匹配从包含<name>gba<的行开始到包含<extension>的行结束的行范围
    • 这是基于给定的示例,如果需要更健壮的匹配条件,可以修改正则表达式
  • {}有助于将仅针对给定匹配条件执行的命令分组
  • 对于这样的线路范围:
    • /<extension>/仅匹配此行
    • /.sh/!检查其是否具有.sh
    • s/</extension>/ .sh&/.sh

如果您对awk满意,请尝试以下操作。用所示样品进行书写和测试。

awk '
/<name>/{ found="" }
/<name>gba</name>/{
found=1
}
found && /<extension>/ && !/.sh</{
sub(/<//," .sh&")
found=""
}
1
'  Input_file

解释:添加以上详细解释。

awk '                     ##Starting awk program from here.
/<name>/{ found="" }
/<name>gba</name>/{      ##Searching string <name>gba</name>
found=1                 ##Setting found to 1 here.
}
found && /<extension>/ && !/.sh</{   ##Checking found is set and <extension> is found in line then do following.
sub(/<//," .sh&")      ##Substituting </ with space .sh and matched value in current line.
found=""                ##Nullifying found here.
}
1                         ##Printing current line here.
'  Input_file             ##Mentioning Input_file here.

这可能对你有用(GNU sed(:

sed '/<name>gba</name>/{:a;n;/</extension>/!ba;/.sh/!s/</extension/ .sh&/}' file

关注包含<name>gba</name>的行。

打印当前行,获取下一行,如果该行不包含</extension>,则重复。

否则,如果当前行尚未包含.sh,请将其置于上面的字符串之前。

最新更新