在 bash 脚本中使用 sed 替换多行模式

Posted

技术标签:

【中文标题】在 bash 脚本中使用 sed 替换多行模式【英文标题】:Multiline pattern replacement with sed in bash script 【发布时间】:2021-09-12 05:01:37 【问题描述】:

尝试用两个字符,替换多行

如果可以搜索到下面的内容并用上面的替换,那么问题就解决了。

模式遇到时是这样的:

        ,

      ]
    
  




  "query": 
    "bool": 
      "minimum_should_match": 1,
      "should": [

这些是我目前尝试过的方法

    #using \ and spaces
combinedDSL=$(echo "$initialDSLs"|sed 's/\
      ]\
    \
  \
\
\
*\
\
  "query": \
    "bool": \
      "minimum_should_match": 1,\
      "should": [\
/,/' )

echo "$combinedDSL"

#using line breaks \n 

combinedDSL2=$(echo "$initialDSLs|"sed N 's/\n]\n\n\n\n\n*\n\n"query": \n"bool": \n"minimum_should_match": 1,\n"should": [\n/,/')
echo "$combinedDSL2"

这里是完整的上下文:


  "query": 
    "bool": 
      "minimum_should_match": 1,
      "should": [
    

        
          "wildcard": 
            "author_place": "*city*"
          
        ,
        
        
          "wildcard": 
            "meta.title.results": "*state*"
          
        ,

      ]
    
  




  "query": 
    "bool": 
      "minimum_should_match": 1,
      "should": [
    

            
            "wildcard": 
                "author": "*cat*"
            
            ,
            
            
            "wildcard": 
                "meta.hashtag.results": "*Monkey*"
            

      ]
    
  

【问题讨论】:

edit 你的问题是在上下文中显示目标行,这些行被你不想匹配的行包围,并在给定输入的情况下添加预期的输出。 这看起来像 JSON,这意味着您需要使用像 jq 这样的 JSON 感知工具来处理它。 我已将上下文添加到问题中。 @埃德莫顿 您提供的“上下文”中没有任何部分与您要替换的字符串匹配。每一行之间有不同数量的空白行,一个逗号在另一个中不存在,并且缺少换行符和不同的缩进。请清理您的示例,以便您要查找的字符串存在于您的示例输入中。 通过大量工作,您可能可以创建一个复杂的正则表达式,为您的特定 JSON 文件完成这项工作。但在我看来,这是该项目的错误工具。最好学习如何使用现有的许多 JSON 工具,并且下次更加灵活。 【参考方案1】:
$ cat tst.sh
#!/usr/bin/env bash

old='        ,

      ]
    
  




  "query": 
    "bool": 
      "minimum_should_match": 1,
      "should": [
'

new='
,'

# https://***.com/questions/29613304/is-it-possible-to-escape-regex-metacharacters-reliably-with-sed
# explains how in the script below we turn "old" above into a robust
# regexp that's forgiving of white space differences in the target file
# and deactivate the possible backreference in "new".

old="$old" new="$new" awk '
    BEGIN 
        old = ENVIRON["old"]
        new = ENVIRON["new"]

        # Deactivate possible regexp metachars in "old"
        gsub(/[^^\\[:space:]]/,"[&]",old) # deactivate all non-space chars except ^ and \
        gsub(/\^/,"\\^",old)            # deactivate ^
        gsub(/\\/,"\\\\",old)           # deactivate \

        # Make any literal white space present in "old" match all white space
        gsub(/[[:space:]]+/,"[[:space:]]+",old)

        # Deactivate possible backreference metachars in "new"
        gsub(/&/,"\\&",new)             # deactivate &
    
    
        # Create a single input record out of the whole input file
        rec = (NR>1 ? rec RS : "") $0
    
    END 
        gsub(old,new,rec)
        print rec
    
' "$@:--"

$ ./tst.sh file

  "query": 
    "bool": 
      "minimum_should_match": 1,
      "should": [


        
          "wildcard": 
            "author_place": "*city*"
          
        ,

        
          "wildcard": 
            "meta.title.results": "*state*"
          
,
            "wildcard": 
                "author": "*cat*"
            
            ,

            
            "wildcard": 
                "meta.hashtag.results": "*Monkey*"
            

      ]
    
  

【讨论】:

以上是关于在 bash 脚本中使用 sed 替换多行模式的主要内容,如果未能解决你的问题,请参考以下文章

用 Bash 脚本中的 sed 替换文件中的版本号

如何在 bash 脚本中用多行/流替换单个流/行?

Bash 脚本:如何用 sed 替换 package.json 中的文本

sh Bash - 通过sed替换行脚本

Bash:从脚本中查找并替换文本

如何查找多个文件、检查重复文件并用 bash、sed 脚本替换