Bash sed匹配模式的第二个匹配项

Bash sed匹配模式的第二个匹配项,bash,unix,awk,sed,Bash,Unix,Awk,Sed,更新问题: 我有一个文件,其中包含以下两种格式之一的代码块: 一, 二, 我需要将$Cc变量中的电子邮件id(第二次出现)替换为两种格式的新电子邮件id 我有以下sed命令来执行此操作 sed '\|HAD PROBLEMS|,/}/ s/$Cc = \(\"[A-Za-z0-9]*\)\(.*\)\([A-Za-z0-9]*\)\@example.com\"/\$Cc = "new email\\@example.com"/' test.txt 此命令将仅替换if{}块中的$Cc变量的电子邮

更新问题:

我有一个文件,其中包含以下两种格式之一的代码块:

一,

二,

我需要将$Cc变量中的电子邮件id(第二次出现)替换为两种格式的新电子邮件id

我有以下sed命令来执行此操作

sed '\|HAD PROBLEMS|,/}/ s/$Cc = \(\"[A-Za-z0-9]*\)\(.*\)\([A-Za-z0-9]*\)\@example.com\"/\$Cc = "new email\\@example.com"/' test.txt
此命令将仅替换if
{}
块中的
$Cc
变量的电子邮件id(第一次出现
$Cc
),因为我的结束匹配模式是“}”。我还想替换第二个
$Cc
中的电子邮件id。如何匹配第二次出现的
“}”

下面提到的解决方案适用于第一种格式。但我需要一个通用的解决方案,这两种格式都适用。谁能帮忙吗


我希望描述清楚。

在我看来,awk将是一种更清晰的语言来表达这个问题

awk '/HAD PROBLEMS/{x=1} /}/{x++} x==2&&/\$Cc =/{sub(/[a-z]+\\@[a-z.-]+/,"new@example.com"); unset x} 1' input.txt
或者,为了便于评论,将其隔开:

# search for your start pattern, set a counter.
/HAD PROBLEMS/ {x=1}        

# increment the counter at the first close-squigly.
/}/ {x++}                   

# If we've done our increment and we're on the right line,
x==2 && /\$Cc =/ {          
  # substitute the existing address with a new one,
  sub(/[a-z]+\\@[a-z.-]+/,"new@example.com");
  # and reset our counter.
  unset x
}

# Print the current line.
1                           

您的输入不清楚,请使用正确的预期输出修复脚本中的语法问题。为什么要将$Cc设置为相同的值,而不考虑$to?这是打字错误吗?@Inian,你的sed脚本确实替换了这两个实例,但这不是OP想要的。他只想要出现在
if
else
块中的第二个实例,该块位于单词
有问题之后。虽然这很可能是可以在sed中表达的东西,但它可能需要使用sed的保持空间和类似
x;s/[a-z]+\\@[a-z.-]+/new@example.com/2;p
,一旦您知道如何仅将文件的重要部分放入sed的保留空间。太晚了,我想不出来,所以。。。救命啊@戈蒂:要是要求这么明确就好了!:)这对我有用。但我必须进行就地搜索和替换。我有awk版本3.1.5正在运行,我无法使用上面的命令进行替换。以上答案是否有sed版本?这将非常有用。Sed-inplace只需将文件复制到一个临时文件,然后重命名。您可以使用外壳包装器自己完成此操作<代码>awk'/HAD PR..file.txt>输出。$$&&mv输出。$$file.txt
它正在工作。我还需要你的帮助。我有一行类似的代码。但同样的解决方案不起作用。它是否只在新行中查找“}”?你能帮忙吗$主题=“有问题”;if($To){$Cc=“xyz\@abc.com”}else{$Cc=“xyz\@abc.com”}所以注释对于代码来说是一个可怕的地方,特别是如果它是未格式化的。请更新您的问题,我们将从那里开始。另外,您是否正在寻求我的答案打算修改的代码方面的帮助?这可能是一个新问题的基础,因为这个问题只是关于修改文本文件。感谢您的反馈。我已经更新了问题。
awk '/HAD PROBLEMS/{x=1} /}/{x++} x==2&&/\$Cc =/{sub(/[a-z]+\\@[a-z.-]+/,"new@example.com"); unset x} 1' input.txt
# search for your start pattern, set a counter.
/HAD PROBLEMS/ {x=1}        

# increment the counter at the first close-squigly.
/}/ {x++}                   

# If we've done our increment and we're on the right line,
x==2 && /\$Cc =/ {          
  # substitute the existing address with a new one,
  sub(/[a-z]+\\@[a-z.-]+/,"new@example.com");
  # and reset our counter.
  unset x
}

# Print the current line.
1