在下一行进行模式匹配并使用 sed 进行替换

在下一行进行模式匹配并使用 sed 进行替换

我有包含以下数据的文件

猫文件:

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打印结果。

此后,如果它是最后一行($),则保留空间中还有一些内容尚未打印(来自Hx)。我们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和默认的打印规则(即缺少)自然可以完成工作。它们非常适合您想要做的事情。PD-n


笔记

这两种解决方案都保持第一行完整,即使它以 开头+

相关内容