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

Awk sed查找正则表达式模式,然后查找下一个正则表达式模式(变量多行)并替换,awk,sed,Awk,Sed,我试图找到一种方法,使用sed将字符串“.sh”插入到文本文件的特定行中。我的问题是,我只想在前面的正则表达式匹配的情况下插入字符串,它还必须支持“name”和“extension”标记之间的可变行数,并且是幂等的,因此我可以对“extension”标记的空格分隔列表只插入一次“.sh”就可以多次运行它 以下是文本文件的一个小片段:- <name>gba</name> <fullname>Game Boy Advance</fullnam

我试图找到一种方法,使用sed将字符串“.sh”插入到文本文件的特定行中。我的问题是,我只想在前面的正则表达式匹配的情况下插入字符串,它还必须支持“name”和“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>
gba
游戏机前进
任天堂
2001
便携式的
/存储/ROM/gba
.gba.gba.zip.zip.7z.7z
因此,我想将
.gba.gba.zip.zip.7z.7z
更改为
.gba.gba.zip.zip.7z.sh
仅当名称标签为
gba

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


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

如果您对
awk
没有问题,请尝试以下内容。使用显示的样本进行书写和测试

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

找到&&/&&!/\。sh使用GNU-sed测试(其他实现的语法可能不同):

sed'/gba这可能适合您(GNU-sed):


sed'/gba/{:a;n;/!ba;/\.sh/!s/谢谢!如果我执行上面的代码并将其写入与输入文件相同的名称(使用
/tmp/test.txt>tmp和&mv-tmp/tmp/test.txt
),我对awk没问题然后重新运行,我看到扩展标记列表中重复插入了“.sh”,因此它似乎不是幂等的。@binhex,当然,我又添加了一个条件,它只在
.sh
不存在时才进行替换,请检查一次,并让我知道它是如何运行的,干杯。谢谢RavinderSingh13,我认为您的修订有效对于@Sundeep的sed-only解决方案,我将不得不给出公认的答案,但我非常感谢您的回复和代码分解。
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.
sed '/<name>gba<\/name>/{:a;n;/<\/extension>/!ba;/\.sh/!s/<\/extension/ .sh&/}' file