我正试图找到一种方法,使用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
,请将其置于上面的字符串之前。