sed 多行搜索替换

sed multiline search-replace

我得到了令人讨厌的旧语法的 Fortran 代码,想移植到新语法。 我的 sed 命令

sed -nr 'N;s/\n\s*\d\D\s*//g' file 

应该可以找到带编号的换行符,但由于我不知道的原因而不起作用。我已经在这里查看了许多 multiline-sed 问题,但我仍然无法消除我的误解。根据我的理解,命令是这样工作的:

N                   append next line to pattern space; thus pattern space has two lines with \n in between
s///g               usual search-replace
\n\s*\d\D\s*        matches a newline followed by \s*, a digit, a non-digit and a \s* again

源代码看起来像

   if(condition) then 
         call func1(v1, v2, v3, v4
     1              ,v5,v6,v7)
      else
         call func2(v1, v2, v3, v4
     1              ,v5,v6,v7)
      endif
call MPI_BCAST(num(1),1,MPI_DOUBLE_PRECISION
     1     ,masterid,comm,mpinfo)
21      format(' text',2x,f10.5)

并应转换为目标代码

   if(condition) then 
         call func1(v1, v2, v3, v4,v5,v6,v7)
      else
         call func2(v1, v2, v3, v4,v5,v6,v7)
      endif
call MPI_BCAST(num(1),1,MPI_DOUBLE_PRECISION,masterid,comm,mpinfo)
21      format(' text',2x,f10.5)

这是一种适用于给定样本输入的 perl 的可能解决方案:

perl -0777 -pe 's/\n\h*\d\h*(?=,)//g'
  • -0777 将整个输入作为单个字符串
  • \n\h*\d\h* 匹配换行符后跟可选的水平空格后跟数字字符后跟可选的水平空格
    • (?=,) 仅当此类匹配后有逗号字符时才匹配...否则,您需要说明如何不匹配 21 format(' text',2x,f10.5)

有了 GNU sed,但我对这些命令的理解还不够自信:

sed -E 'N; s/\n\s*[0-9]\s*,/,/; P; D'

来自 GNU sed manual:

P Print out the portion of the pattern space up to the first newline.

D If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.

这可能适合您 (GNU sed):

sed -E ':a;N;s/\n\s*[0-9]\s*([^0-9])//;ta;P;D' file

使用第 2 行遍历文件 window。

如果第二行以一些白色或没有白色 space 开头,后跟一个数字,然后是更多或没有白色 space,然后是 non-digit,请替换此行通过 non-digit 并重复。否则打印 window 的第一行,然后删除它并重复。