【问题标题】:Globally matching and replacing multi-line text全局匹配和替换多行文本
【发布时间】:2018-02-01 11:19:25
【问题描述】:

我正在处理一个包含许多文件 (100+) 的项目。

我要更新的每个页面上都有两个 FE 属性。例如,

                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },

我可以单独对“PropOne”和“Prop2”进行 grep,但为了更准确,我宁愿匹配整个属性对象。

有没有办法使用 GREP 之类的方法来查找和更新值?

编辑:预期输出为:

                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },

【问题讨论】:

  • 预期输出是什么?
  • 我想得到 property1: { type: String, notify: true, value: "this is the new PropOne" }, property2: { type: String, notify: true, value: "这是新的 PropTwo" },
  • 不在 cmets 中,更新问题。

标签: bash ubuntu awk sed grep


【解决方案1】:
$ cat old
                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },

$ cat new
                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },

.

$ cat file
lines before
the target
                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },
lines after
the target

$ awk -v RS='^$' -v ORS= '
    ARGIND==1 { old=$0; next }
    ARGIND==2 { new=$0; next }
    s=index($0,old) { $0=substr($0,1,s-1) new substr($0,s+length(old)) }
    { print }
' old new file
lines before
the target
                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },
lines after
the target
$

以上使用 GNU awk 处理多字符 RS 和 ARGIND。如有必要,不难提出 POSIX 版本。它使用字符串比较和替换,因此文件中的正则表达式和/或反向引用元字符将被视为文字,因此不需要任何特殊考虑(例如,如果您尝试使用 sed 或任何其他基于正则表达式的方法) .

【讨论】:

    【解决方案2】:

    这是另一个gnu awk 解决方案:

    awk -v RS='},' 'NF {
       sub(/value: "[^"]*"/, "\"this is new " ($1=="property1:"?"PropOne":"PropTwo") "\"")
    }
    {
       ORS=RT
    } 1' file
    

    输出:

                   property1: {
                        type: String,
                        notify: true,
                        "this is new PropOne"
                    },
                    property2: {
                        type: String,
                        notify: true,
                        "this is new PropTwo"
                    },
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -i '/^\s*property.*: {/,/^\s*},/s/"\(.*\)"/"this is the new &"/' file
      

      这匹配以property 开头并以}, 结尾的一系列行,然后将双引号之间的字符串替换为所需的替换(如果需要,使用反向引用)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-04
        • 1970-01-01
        • 1970-01-01
        • 2012-05-01
        • 2017-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多