sed只替换搜索字符串中的匹配部分

时间:2011-11-26 16:56:46

标签: sed

我有一个包含以下内容的文件:

  

Lorem ipsum dolem file1.jar。

     
      
  • file1.jar(MD5:12345678901234567890123456789012)
  •   
  • file2.jar(MD5:09876543210987654321098765432109)
  •   
  • file3.jar(MD5:24681357902468135790246813579024)
  •   

我想替换第一台MD5。这个sed命令完成了这项任务:

sed "s/file1.*MD5\:\(.*\)/file1.jar \(MD5\: `md5 file1.jar | awk '{print $4}'`\)/"

有没有办法告诉sed只替换匹配的组,而只剩下其余部分?例如:

sed "s/file1.*MD5\:\(.*\)/`md5 file1.jar | awk '{print $4}'`/"

2 个答案:

答案 0 :(得分:6)

您可以使用搜索来指定要匹配的行,然后使用替换中的更简单的正则表达式:

sed "/file1\.jar (MD5: [0-9A-Fa-f]*)/s/(MD5: [^)]*)/(MD5: $(md5 file1.jar | awk '{print $4}'))/"

使用$(...)表示法运行命令。其中最棘手的部分是序列))/"出现的末尾。第一个右括号是$(...)表示法的结尾;第二个是替换文本中的一个字符。

第一个正则表达式/file1\.jar (MD5: [0-9A-Fa-f]*)/相当精确地指定了要匹配的行。然后,知道它是正确的行,替换中的模式可以更简单:搜索部分/(MD5: [^)]*)/只查找带括号的MD5数据,安全知道即使许多其​​他行包含相同的模式,替换只会应用于所需的一行。

我可能倾向于使用:

md5=$(md5 file1.jar | awk '{print $4}')
sed "/file1\.jar (MD5: [0-9A-Fa-f]*)/  s/(MD5: [^)]*)/(MD5: $md5)/"

它澄清了什么是相当大的(并且不涉及SO上的水平滚动条)。您可以在线匹配模式中更精确:

md5=$(md5 file1.jar | awk '{print $4}')
sed "/^file1\.jar (MD5: [0-9A-Fa-f]\{32\})\$/  s/(MD5: [^)]*)/(MD5: $md5)/"

坚持正好32个十六进制数字和行尾的近括号。


其中一条评论问道:

  

sed的运行方式是替换字符串只替换搜索模式中的匹配组吗?例如,给定's/A B \(D\)/C/',它会输出A B C

如果我理解(澄清)问题,那么你可以通过适当的捕获来做你想做的事情 - 但是替换部分必须准确指定你想要的输出(没有你想要的快捷方式)。因此,对于该示例,您可以编写如下内容:

s/\(A B \)\(D\)/\1C/

(捕获\(D\)不需要捕获括号,因为替换时未使用捕获的材料,您可以编写以下任一项:

s/\(A B \)D/\1C/
s/\(A B\) D/\1 C/

你也可以这样做:

/A B / s/D/C/

这有一个搜索(对于A B序列),然后替补查找D并将其替换为C。这基本上是主要答案所暗示的。您也可以这样做:

/\(A B\) D/ s//\1 C/

'空搜索'应重复匹配,但替换必须完整写出,这实际上与之前的命令相同:

s/\(A B\) D/\1 C/

答案 1 :(得分:0)

这应该做(未经测试):

sed "s/(file1.jar \(MD5: )(..............................)/\1`md5 file1.jar | awk '{print $1}'`/"

那是32点,请注意。