【问题标题】:Replace string starting with in between two lines using bash使用bash替换以两行之间开头的字符串
【发布时间】:2017-04-23 04:29:59
【问题描述】:

有没有办法在不使用循环的情况下使用 sed 替换整个文件中字符串的开头?

例如,我的源数据如下:

str_address: 123 main street
str_desc: Apt3
str_desc: 2nd floor
str_city: new york
str_desc: mailing address

现在,该文件将有数千个地址,但我希望“str_desc”出现在“str_address”之后和“@”之前987654324@" 将替换为 "str_address",但在 str_city 之后出现的任何 "str_desc" > 保持不变。

期望的输出:

str_address: 123 main street
str_address: Apt3
str_address: 2nd floor
str_city: new york
str_desc: mailing address

我可以提取此信息,

cat file | awk '/str_city/{f=0} f; /str_address/{f=1}'

给了

str_desc: Apt3
str_desc: 2nd floor

但我无法将第一个“str_desc”更改为“str_address”。

【问题讨论】:

    标签: bash shell awk sed


    【解决方案1】:

    您的awk 提取代码中几乎有完整的解决方案:

    awk '/str_city/{f=0} f; /str_address/{f=1}'
    

    这个想法是:

    • 看到str_address时打开标志。
    • 看到str_city时关闭标志。
    • 如果标志打开,请将 str_desc 替换为 str_address

    基本上是这样(可读形式,顺序很重要):

    awk '
        $1 == "str_address:"           { flag = 1 }
        $1 == "str_desc:" && flag == 1 { $1 = "str_address:" }
        $1 == "str_city:"              { flag = 0 }
                                       { print }
        ' < inputFile >outputFile
    

    这是一个显示它在行动中的成绩单:

    pax$ echo '
         str_address: 123 main street
         str_desc: Apt3
         str_desc: 2nd floor
         str_city: new york
         str_desc: mailing address
         ' | awk '
             $1 == "str_address:"           { flag = 1 }
             $1 == "str_desc:" && flag == 1 { $1 = "str_address:" }
             $1 == "str_city:"              { flag = 0 }
                                            { print }'
    
    str_address: 123 main street
    str_address: Apt3
    str_address: 2nd floor
    str_city: new york
    str_desc: mailing address
    

    当然还有缩小版:

    awk '$1=="str_address:"{f=1}$1=="str_desc:"&&f==1{$1="str_address:"}$1=="str_city:"{f=0}{print}' < inputFile >outputFile
    

    【讨论】:

      【解决方案2】:

      您可以在 sed 中使用地址范围:

      $ sed '/str_address/,/str_city/s/str_desc/str_address/' infile
      str_address: 123 main street
      str_address: Apt3
      str_address: 2nd floor
      str_city: new york
      str_desc: mailing address
      

      这使/str_address/,/str_city/ 范围之外的所有str_desc 保持不变,并用str_address 替换其他s/str_desc/str_address/ 部分。

      【讨论】:

      • 但是这个范围是贪婪的。不是吗??
      • @sjsam 不,它适用于多个块。例如,尝试重复输入示例。
      • @sjsam 不能贪心,sed看一行的时候不知道后面会发生什么。
      猜你喜欢
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 2022-10-24
      • 2021-01-20
      • 2011-10-19
      • 2021-06-20
      • 2012-11-05
      相关资源
      最近更新 更多