如何使用 sed 将带有模式的行与下一行连接起来?

如何使用 sed 将带有模式的行与下一行连接起来?

我在论坛上找不到这个案例,所以才来提问。

这是输入文件:

module  
x(a,b,c)  
module  
y(d,e,f,  
g,h,i)  
module  
z(j,k,l)

输出文件应该是:

module x(a,b,c)  
module y(d,e,f,  
g,h,i)  
module z(j,k,l)

答案1

您要做的是将这些module行与下一行连接起来。

使用sed

$ sed '/^module/N;s/\n//' file
module  x(a,b,c)
module  y(d,e,f,
g,h,i)
module  z(j,k,l)

这是按原样复制和粘贴数据的情况,每行末尾都有空格。

sed命令将在读取时打印每一行,但是当它遇到以 string 开头的行时module,它会在下一行之间附加嵌入的换行符(这就是所做的N)。在打印结果之前,我们通过替换删除换行符。

如果您的数据行尾没有空格,请使用

$ sed '/^module/N;s/\n/ /' file
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)

以防万一您想要这个(假设输入行末尾没有空格):

$ sed -e '/^module/bpp' -e 'H;$bpp' -e 'd' \
      -e ':pp' -e 'x;/^$/d;s/\n/ /g' file
module x(a,b,c)
module y(d,e,f, g,h,i)
module z(j,k,l)

带注释的sed脚本:

/^module/ b print_previous; # print previous record
H;                          # append this line to hold space
$         b print_previous; # print previous (last) record
d;                          # end processing this line

:print_previous;            # prints a record accumulated in the hold space
x;                          # swap in the hold space
/^$/ d;                     # if line is empty, delete it
s/\n/ /g;                   # replace embedded newlines by spaces
                            # (implicit print)

奖励ed内容:

$ printf '%s\n' 'g/^module/ j' ,p Q | ed -s file
module  x(a,b,c)
module  y(d,e,f,
g,h,i)
module  z(j,k,l)

上面的代码将从字符串开始的任何行module与其下一行连接起来。

$ printf '%s\n' 'v/^module/ -,.j' ,p Q | ed -s file
module  x(a,b,c)
module  y(d,e,f,  g,h,i)
module  z(j,k,l)

上面连接任意行不是module从字符串开始以前的线。

答案2

使用 awk:

~ awk '/^module/ {l = $0; getline; printf "%s", l} 1' input-file
module  x(a,b,c)
module  y(d,e,f,
g,h,i)
module  z(j,k,l)

对于以 开头的每一行module,将该行保存在 中l,移动到下一行 ( getline),然后打印保存的行(不带换行符)。然后打印每一行。

答案3

另一种选择:创建ed脚本!

首先预先计算所需的连接数量;然后,它生成一定数量的ed搜索和连接命令,并将它们以及最后的保存和退出通过管道传输到ed

#!/bin/bash
n=$(grep -c '^module *$' input)
{
  for((i=1; i <= n; i++))
  do
    printf '/^module *$/\n.,+1j\n'
  done
  echo w
  echo q
} | ed -s input >/dev/null

答案4

使用(以前称为 Perl_6)

~$ raku -ne '/^module/ ?? (print "$_\t"; put get) !! .put;'  file

或者:

~$ raku -ne '/^module/ ?? (put join "\t", $_, lines[0]) !! .put;' file  

awk上面的 Raku 答案与@muru 的优秀答案类似。在 Raku 中,三元运算符的拼写为测试 ?? 真的 !! 错误的。这些-ne标志按行读取文件而不自动打印。

如果该行以 ed 开头moduleprint则后跟一个\t制表符(可以用任何列分隔符替换)。然后(在第一个示例中)代码指示get下一行及其put内容。在第二个示例中,您打印$_主题变量,并将下一行line[0]加入\t并退出put它。如果没有匹配module(即“False”),则该行简单地退出put

输入示例(行尾已清理):

module
x(a,b,c)
module
y(d,e,f,
g,h,i)
module
z(j,k,l)

示例输出(制表符分隔的列):

module  x(a,b,c)
module  y(d,e,f,
g,h,i)
module  z(j,k,l)

请注意,OP 的输入文本包含尾随空格,因此虽然使用原始输入可能没问题,但要连接的其他示例文本文件可能不包含尾随空格,在这种情况下,“列”将一起运行。因此使用\t上面的方法来间隔列。

https://docs.raku.org
https://raku.org

相关内容