我有包含以下数据的文件
猫文件:
ABC
+123
+456
XYZ
+789
我想在下一行的开头搜索“+”并删除“+”并与当前行连接
输出应该是:
ABC 123 456
XYZ 789
答案1
关于sed
我想在下一行的开头搜索“+”并删除“+”并与当前行连接
如果您想使用,sed
那么上面的内容并不能很好地表达您想要做的事情。在sed
您阅读下一行之前,您无法检查下一行,但那时它已经是当前行了。
在sed
你操作模式空间,通常当前行会出现在其中。还有保持空间您可以在其中保留前一行。
你写的是“下一行”、“当前行”。在我看来,最好分别用“当前行”和“上一行”来思考。
平庸的解决方案
下面的代码可以工作,你可以将其描述为一堆if。
sed -n '
1 { $ {p;q}
h
}
1! { /^+/ H
/^+/! {x;s/\n+/ /g;p}
}
$ { g;s/\n+/ /g;p
}
'
首先,如果我们在第一行(1
)并且它恰好是最后一行($
),我们只需p
打印并q
退出。如果第一行不是最后一行,我们h
将其保存在保留空间中。
对于不是第一行 ( 1!
) 的每一行,我们检查它是否以 开头+
。如果是 ( /^+/
),我们将其附加到保持空间 ( H
);这样保持空间就会累积行。如果行不是以+
( /^+/!
) 开头,我们将x
更改保持空间和模式空间的内容,因此当前行单独存储在保持空间中,而先前保持的行已准备好在模式空间中进行操作。我们搜索 ( s
) 所有 ( g
) 个换行符后跟+
( \n+
) 的位置,并将每个位置替换为一个空格 ( )。最后我们
p
打印结果。
此后,如果它是最后一行($
),则保留空间中还有一些内容尚未打印(来自H
或x
)。我们g
将其保留到模式空间并像以前一样继续将其打印为一行。
-n
默认情况下不打印sed
。我们的代码仅在明确使用时才打印p
。
更好的解决方案
对于您想要执行的操作和类似任务,有一个巧妙的方案N
,即P
,,D
。该方案根本不使用保持空间。它无需 即可工作-n
。
sed ':start;N;s/\n+/ /;t start;P;D'
:
表示标签,start
是任意名称。N
将输入的下一行附加到模式空间。然后s
尝试用空格替换换行符后跟的+
;这仅在新附加的行以 开头时才有效+
。如果s
有效则将t start
跳转到:start
,因此N
将附加另一行,依此类推。这样,模式空间就会精确地积累您所需的内容,+
一次转换一个 <newline>,直到出现不以 开头的行+
,因此s
找不到 的匹配项\n+
。
s
未找到匹配项后\n+
,t
不跳转,P
执行。P
打印模式空间直到第一个嵌入的换行符。这正是在最新N
附加不以 开头的行之前累积的数据+
。接下来D
删除刚刚打印的内容并开始新循环而不读取新行输入。尚未打印的文本(即不以 开头的行+
)保留在模式空间中并N
可以附加到其中。
请注意,代码非常简单。以前(在平庸的解决方案中),我们需要为第一行添加一个特殊情况,为最后一行添加另一个特殊情况。在这里,,N
和默认的打印规则(即缺少)自然可以完成工作。它们非常适合您想要做的事情。P
D
-n
笔记
这两种解决方案都保持第一行完整,即使它以 开头+
。