我有一个文件,偶尔会有分割线。该行以“+”开头(前面可能有空格)来表示分割。
line 1
line 2
+ continue 2
line 3
...
我想加入分割线:
line 1
line 2 continue 2
line 3
...
使用 sed。我不清楚如何将一行与前面加入一行。
有什么建议吗?
这可能对你有用:
sed 'N;s/\n\s*+//;P;D' file
这实际上是四个命令:
N
s/\n\s*+//
P
D
相关手册页部分是
要添加 1 条或多条
+
行,请使用:
sed ':a;N;s/\n\s*+//;ta;P;D' file
在 sed 中执行此操作当然是一个很好的练习,但在 Perl 中则非常简单:
perl -0777 -pe 's/\n\s*\+//g' input
POSIX sed 对保留空间的不同使用...在合并行之前将整个文件加载到保留空间中。
sed -n '1x;1!H;${g;s/\n\s*+//g;p}'
1x
在第一行,将该行交换到空的保留空间1!H
在非第一行,追加到保留空间$
:
g
获取保留空间(整个文件)s/\n\s*+//g
替换前面的换行符 +
p
打印所有内容输入:
line 1
line 2
+ continue 2
+ continue 2 even more
line 3
+ continued
成为
line 1
line 2 continue 2 continue 2 even more
line 3 continued
这个(或potong的答案)可能比
sed -z
实现更有趣,如果需要其他命令来对数据进行其他操作,您可以简单地将它们粘贴在1!H
之前,而sed -z
会立即将整个文件加载到模式空间。这意味着您在任何时候都不会操纵单行。 perl -0777
也一样。
换句话说,如果您还想删除以
*
开头的注释行,请添加 /^\s*\*/d
来删除该行
sed -n '1x;
/^\s*\*/d;
1!H;${g;s/\n\s*+//g;p}'
对:
sed -z 's/\n\s*+//g;
s/\n\s*\*[^\n]*\n/\n/g'
前者在保留空间中逐行的积累使您处于经典的 sed 行处理状态,而后者的
sed -z
将您转入可能是一些痛苦的子字符串正则表达式。
但这只是一种边缘情况,你总是可以将
sed -z
通过管道传回到 sed 中。所以+1。
互联网搜索脚注:这是 SPICE 网表语法。
我不偏爱 sed,所以这对我来说是一个很好的挑战。
sed -n '1{h;n};/^ *+ */{s// /;H;n};{x;s/\n//g;p};${x;p}'
在 awk 中,这大约是:
awk '
NR == 1 {hold = $0; next}
/^ *\+/ {$1 = ""; hold=hold $0; next}
{print hold; hold = $0}
END {if (hold) print hold}
'
如果最后一行是“+”行,则 sed 版本将打印尾随空白行。不知道如何抑制它。
您可以在 Ex 模式下使用 Vim:
ex -sc g/+/-j -cx file
g
全局搜索-
选择上一行j
与下一行连接x
保存并关闭针对
sed
版本的解决方案,可以读取 NUL 分隔的数据,就像这里 GNU Sed 的 -z
:
sed -z 's/\n\s*+//g'
与 potong 的解决方案相比,它的优点是能够连接以
+
开头的多条线。例如:
line 1
line 2
+ continue 2
+ continue 2 even more
line 3
成为
line 1
line 2 continue 2 continue 2 even more
line 3