sed 在某些分隔符之间的另一个字符之前添加字符

sed 在某些分隔符之间的另一个字符之前添加字符

所以我想回答以下问题sed + 仅当不存在时才在字符串前添加单词sed——当前面的字符不是某个字符时替换字符串中的字符并更进一步。

假设我有一个文件,我想将其全部替换_\_,但我有两个限制:

  1. 如果_前面已经有 a\那么我不希望发生任何事情。 (我们从来没有得到过\\所以不必担心这种情况)
  2. 我们应该仅有的_如果出现在两个分隔符之前,请进行此替换。例如,在start[和之间]end

例如,以下内容:

Pretending_we have \_ some start[text that\_is really_cool]end.
Then \_nothing_ would start[happen_ to\_ that crew_]end

会被转换为

Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end

笔记:我知道在某些情况下,我们希望通过将每个实例替换\_为未使用的内容,然后将所有_实例替换为\_,然后反转第一个更改来链接 sed。但我不想这样做,因为我不知道代码中可能存在哪些其他字符,所以如果可能的话我想直接这样做。

另外,我将在 vim 和终端中执行此操作(vim 作为测试运行以确保其正常工作,然后在终端中处理 11 个不同的文件。)我不太了解两者之间的差异,但是我想我会提到它,以防其中一个比另一个更容易。

编辑:回答一些提出的问题:

  1. perl/sed/vim 都是可以接受的方法来处理这个问题。只是不确定最好的方法是什么,我对 sed/vim 的正则表达式更满意,因此我提到了这些。 (通过将 sed 和 vim 混为一谈,我认为我造成了混乱,对此感到非常抱歉。我习惯使用 sed 和 vim 正则表达式来处理我的大部分正则表达式需求,并且从我注意到的情况来看,通常我在其中所做的工作完美地工作在 sed 和 vim 上。所以我假设他们使用相同的正则表达式处理,但这可能不是我应该做的安全假设,并且会对此进行查找。
  2. 我用的是ubuntu
  3. 一般来说,开始/结束分隔符将在同一行上,因此从理论上讲,这可以是一个安全的假设(尽管如果您知道如何做到这一点,那么行并不重要,这对于未来的人们看待这样的问题也是有好处的)

答案1

我会用perl它:

perl -pe 's{start\[.*?\]end}{$& =~ s{\\?_}{\\_}gr}ge' < your-file

我们s将所有 ( g)start[...]end序列替换为相同的序列($&其中包含正则表达式匹配的内容),我们s替换并r返回所有 ( g) _s ,可选地 ( ?) 前面带有\with \_。该e标志表示替换 ( $& =~ s{\\?_}{\\_}gr) 将被e评估为代码。

假设没有嵌套start[...]end.

如果start[...]ends 可能跨越多行,请添加该-0777选项(将记录分隔符设置为不可能的值),以便将输入作为一个整体进行处理,而不是一次处理一行。


s/pattern/replacement/flags¹ 使用与 in相同的方法sed,除了 inperl我们也可以编写它s{pattern}{replacement}flags,这有助于嵌套和易读

答案2

仅限 GNU sed:

sed -r ':1;s/(start\[.*[^\])(_.*\]end)/\1\\\2/;t1' file

如果您需要进行替换,则-i最后设置该标志-ri

答案3

您可以使用 awk 命令来完成这项工作。可以方便地将方括号临时替换为其他字符,例如#

cat yourfile.txt| tr '[]' '#'

现在将上述结果通过管道传递给此命令:

awk -F# 'OFS=""; {for (i=1;i<=NF; i++)  if(i%2==0){ gsub("\\\\","",$i);gsub("_","\\_",$i);$i="["$i"]"} print $0}' 

答案4

使用 GNU awk 进行多字符RSRT和第三个参数match()

$ awk -v RS=']end' '{ORS=RT} match($0,/(.*start\[)(.*)/,a) { gsub(/\\?_/,"\\_",a[2]); $0=a[1] a[2] } 1' file
Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end

相关内容