首页 > 解决方案 > 替换字符串,但仅当它是该字符串在特定行之前的最后一次出现时

问题描述

我正在将自定义标记语言转换为 TeX。

我有一个这样的文件:

\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
e

\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
e

我需要结果是这样的:

\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}

\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}

通知e本身在一行上,表示一组数据的结束,它只是被一个右括号替换。

我可以简单地使用这个:

sed -i 's/^e$/}/g' file.tex

结果是:

\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
}

\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
}

问题是,我还需要一个匹配的起始括号来在e.

一种思考方式是:

  1. 替换每次出现的}.
  2. 但仅当该事件出现在行尾时。
  3. 并且仅当它是在e完全单独出现之前出现的最后一个出现。

这是我能想到的最接近的,不知道如何匹配不包含更多匹配项的任意数量的行}$

sed -i 's/}$\n.*\n.*\n.*\n^e$/}{&}/g' file.tex

如何将最后的额外文本包装在{and中}

标签: sed

解决方案


使用awk空的RS. 这是一个gnu-awk解决方案:

awk -v RS= '{sub(/.*}/, "&{"); sub(/\ne$/, "\n}"); ORS=RT} 1' file

\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}

\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}

或在任何版本中awk

awk -v RS= '{sub(/.*}/, "&{"); sub(/\ne$/, "\n}\n")} 1' file

推荐阅读