Grep搜索多行字符串模式linux

时间:2013-11-19 10:18:23

标签: linux replace grep

我在文件中有以下文字说test.txt: (注意:可以有更多'边界:CRAC'块)

BOUNDARY: CRAC2OUT
  Boundary Type = INLET
  Location = CRAC_OUT2
  BOUNDARY CONDITIONS:
    FLOW REGIME:
      Option = Subsonic
    END
    HEAT TRANSFER:
      Option = Static Temperature
      Static Temperature = 16 [C]
    END
    MASS AND MOMENTUM:
      Normal Speed = (3.8/1.185)[m^3 s^-1]/area()@CRAC2OUT
      Option = Normal Speed
    END
    TURBULENCE:
      Option = Medium Intensity and Eddy Viscosity Ratio
    END
  END
END
BOUNDARY: CRAC3OUT
  Boundary Type = INLET
  Location = CRAC_OUT3
  BOUNDARY CONDITIONS:
    FLOW REGIME:
      Option = Subsonic
    END
    HEAT TRANSFER:
      Option = Static Temperature
      Static Temperature = 16 [C]
    END
    MASS AND MOMENTUM:
      Normal Speed = (3.8/1.185)[m^3 s^-1]/area()@CRAC3OUT
      Option = Normal Speed
    END
    TURBULENCE:
      Option = Medium Intensity and Eddy Viscosity Ratio
    END
  END
END
BOUNDARY: CRAC4OUT
  Boundary Type = WALL
  Location = CRAC_OUT4
  BOUNDARY CONDITIONS:
    HEAT TRANSFER:
      Option = Adiabatic
    END
    MASS AND MOMENTUM:
      Option = No Slip Wall
    END
    WALL ROUGHNESS:
      Option = Smooth Wall
    END
  END
END

我需要搜索说CRAC3OUT并用17代替16替换其块中的静态温度值,同样用4.8而不是3.8改变它的正常速度。 我只需要更改CRAC3OUT的那个块。

如何使用grep或pcregrep执行此操作?

3 个答案:

答案 0 :(得分:1)

我不认为可以在文本中进行那种转换。当您必须保留不同数量的空白字符时,无效,因此可能是一个不错的选择,使用标记仅更改该块:< / p>

perl -ne '
    @f = grep { /./s } split /((?>\s+))/;
    if ( $_ =~  m/^BOUNDARY:\s+CRAC3OUT/ ) { $block = 1; }
    if ( $f[1] eq q|BOUNDARY:| ) { $block = 0; }
    if ( $block ) {
        if ( $f[1] eq q|Static| and $f[3] eq q|Temperature| ) {
            $f[7] = 17;
        }
        if ( $f[1] eq q|Normal| and $f[3] eq q|Speed| ) {
            $f[7] =~ s/\d*\.\d*/4.8/;
        }
    }
    printf qq|%s|, join q||, @f;
' test.txt

它产生:

...
BOUNDARY: CRAC3OUT
  Boundary Type = INLET
  Location = CRAC_OUT3
  BOUNDARY CONDITIONS:
    FLOW REGIME:
      Option = Subsonic
    END
    HEAT TRANSFER:
      Option = Static Temperature
      Static Temperature = 17 [C]
    END
    MASS AND MOMENTUM:
      Normal Speed = (4.8/1.185)[m^3 s^-1]/area()@CRAC3OUT
      Option = Normal Speed
    END
    TURBULENCE:
      Option = Medium Intensity and Eddy Viscosity Ratio
    END
  END
END
...

答案 1 :(得分:1)

perl -i -lne 'if(/^\s*Static Temperature/ && $f==1){s/16/17/g;};
              if(/^\s*Normal Speed =/ && $f==1){s/4\.8/3.8/g;$f=0};
              $f=1 if(/BOUNDARY: CRAC3OUT/);
              print $_' your_file

答案 2 :(得分:0)

grep不适合替换任何内容。您应该通过指定要处理的范围来使用sed,但我发现很难使用您的示例正确地扩展范围。 sed也无法真正使用上下文解析复杂语言(就像您使用该块结构一样)。

但是,如果您只能处理从包含Normal Speed = (的行到包含BOUNDARY: CRAC3OUT并且BOUNDARY: CRACxOUT≠{{的行的块中包含x的行1}},然后你可以使用这个简单的3脚本:

sed

但请记住,这可能会失败(即产生不需要的结果),例如,如果您的sed '/BOUNDARY: CRAC3OUT/,/BOUNDARY: CRAC[^3]OUT/s/\(Normal Speed = (\)[^/]*/\14.8/' 块是输入中的最后一个(后面没有其他块),而另一行包含{{1}跟随输入中的某个地方。

为简洁起见,该脚本仅将BOUNDARY: CRAC3OUT更改为Normal Speed = (。从3.84.8的更改当然也是如此。