Sed 合并两个模式之间的行,包括第一个模式,但不包括第二个模式。两个图案相同

Sed 合并两个模式之间的行,包括第一个模式,但不包括第二个模式。两个图案相同
Input:
1:
aaa
bbb
2:
xxx
yyy,
zzz
3:
ccc
4:
5: 
xxx

yyy

输出:

1: aaa bbb
2: xxx yyy, zzz
3: ccc
4:
5: xxx yyy

:$要求:合并模式 1和模式 2之间的所有行:$(包括模式 1 但不包括模式 2)

正则表达式匹配::$
尝试过:

sed '/:$/{n;:l N;/:$/b; s/\n/ /; bl}' | sed '/:$/!b;/:$/N;/:$/!{s/\n//g}' -E

答案1

使用 Perl:

$ perl -0 -pe 's/\n+/ /g;
               s/ (\d+:)/\n$1/g;
               s/^\n+//;
               s/ +$/\n/' input.txt 
1: aaa bbb 
2: xxx yyy, zzz 
3: ccc 
4: 
5: xxx yyy 

(为了便于阅读,在脚本中添加了换行符。它按原样运行,或者您可以删除它们以获得难以理解的单行代码)

  • 首先,它用一个空格替换一个或多个换行符的所有实例(注意:这具有删除/忽略空行的额外有用的副作用)。
  • 然后它替换所有实例中的空格一个空格、一个或多个数字和一个:带换行符。
  • 然后它删除字符串开头的所有前导换行符,并用单个换行符替换字符串末尾的所有尾随空格。这是必需的,因为之前的 s/// 替换操作将所有换行符替换为空格。

-0选项告诉 perl 使用 NUL 作为输入记录分隔符,并且由于输入不包含任何 NUL,这使得它将整个输入文件作为一个长字符串处理。

perl 的-p选项使其工作方式类似于sed用“读取、处理和自动打印”循环包装整个单行脚本。顺便说一句,-nperl 相当于 sed 的-n选项(“读取、处理但不自动打印”循环)。

man perlrun有关这些 、 和 选项的详细信息-0-p请参阅-n

答案2

awk

$ awk -v ORS= '/:$/{print n; n="\n"; s=""} {print s $0; s=" "} END{print n}' ip.txt
1: aaa bbb
2: xxx yyy, zzz
3: ccc
4:
5: xxx  yyy
  • -v ORS=输出记录分隔符的空值
  • /:$/{print n; n="\n"; s=""}
    • 第一次n将为空(以避免在第一行之前打印换行符)
    • s每次找到匹配项时都会被清空
  • {print s $0; s=" "}
    • 打印s后跟输入行
    • s仅对于不以以下结尾的行来说是空格字符:

答案3

您可以使用“可调整大小”的滑动窗口 -$!N通常与 一起使用,P并且D只有在这里您需要在条件下执行此操作:将行累积到模式空间中,只要模式空间不匹配,就用空格替换换行符,/:$/否则打印并删除到换行符并重复:

sed '/:$/{
:do
$!N;/:$/{
P;D
}
s/\
/ /
t do
}' infile

如果您更喜欢gnu sed单行语法:

sed '/:$/{:do;$!N;/:$/{P;D;};s/\n/ /;t do}' infile

答案4

使用 tr 和 sed 可能更容易:

$ tr '\n' ' ' <infile | sed 's/ [0-9]/\n&/g' | sed 's/^ //'
1: aaa bbb
2: xxx yyy zzz
3: ccc
4:
5:  xxx yyy

(如果对齐不是问题,您甚至可以省略上面代码中的第二个 sed)

相关内容