【问题标题】:Replace a string in the file outside curly braces only仅在大括号外替换文件中的字符串
【发布时间】:2024-01-14 17:23:01
【问题描述】:

我需要替换文件中的一些字符串,但是当字符串在花括号内时,我需要跳过它。类似的东西

sed -i '/[^{].*foo.*[^}]/ s/foo/bar/g' test.f 

测试文件 test.f 包含如下内容:

bar foo {foobar}bar {foo}

这应该只搜索未包含在大括号中的字符串中的 foo。所以结果应该是:

bar bar {foobar}bar {foo}

大括号中的所有内容都应该被忽略,即如果字符串以“{”开头,则应该忽略它,直到该行中对应的“}”。

这不必由 sed 执行。非常感谢。

示例输入:

bar foo {foobar}bar {foo}
foo { foo { foo } foo } foo
foo { foo } foo { foo } foo

预期输出:

bar bar {foobar}bar {foo}
bar { foo { foo } foo } bar
bar { foo } bar { foo } bar

【问题讨论】:

  • bar { foofoo } bar 这样的字符串会发生什么?
  • 嵌套卷曲应该怎么办? foo { foo { foo } foo } foofoo { foo } foo { foo } foo.
  • 请使用上述 cmets 中询问的信息更新问题。问题本身目前还不清楚..
  • 基本上大括号内的任何东西都应该被输入,如果里面有另一个大括号也没关系。因此,您的示例的结果将是 bar { foo { foo } foo } bar 和 bar { foo } bar { foo } bar。
  • 是的 Ed,这就是我的意思,使用单个正则表达式几乎不可能使用标准 shell 实用程序。

标签: bash awk replace sed curly-braces


【解决方案1】:
$ cat tst.awk
{
    gsub(/foo/,RS)
    numChars = length()
    rec = ""
    for (charNr=1; charNr<=numChars; charNr++) {
        char = substr($0,charNr,1)
        if ( char == "{" ) { depth++ }
        if ( char == "}" ) { depth-- }
        rec = rec ((char == RS) && (depth == 0) ? "bar" : char)
    }
    gsub(RS,"foo",rec)
    print rec
}

$ awk -f tst.awk file
bar bar {foobar}bar {foo}
bar { foo { foo } foo } bar
bar { foo } bar { foo } bar

【讨论】:

  • 这是正确的方法,而不是任何基于正则表达式的解决方案 ++
  • 是吗?此外 gsub() 甚至在这里每行使用两次
  • 每行调用 gsub() 两次不是问题。我们将看看是否有人提出了基于正则表达式的解决方案进行比较。
  • 检查我的.. 我承认我只是好奇。我可能会输掉那场比赛
【解决方案2】:

只是为了好玩!

awk '{sub(/foo/,"bar")}{sub(/ foo$/," bar")}{sub(/} foo {/,"} bar {")}1' file
bar bar {foobar}bar {foo}
bar { foo { foo } foo } bar
bar { foo } bar { foo } bar

【讨论】: