Regex 使用sed删除几行上的\n

Regex 使用sed删除几行上的\n,regex,sed,Regex,Sed,我试图使用sed删除两个搜索模式之间的所有换行符 我第一次发现了它,它教会了我如何在两种模式之间搜索 sed -e '/begin/,/end/{s/begin/replacement/p;d}' 然后我找到了一个方法来帮助删除文件中的所有换行符 sed ':a;N;$!ba;s/\n/ /g' 我试图将这两个答案结合起来,得出以下结论: sed -e '/begin/,/end/{:a;N;$!ba;s/\n/ /p;d}' 然而,这并不完全有效。它将替换从正确行开始的换行符,但会一直持

我试图使用sed删除两个搜索模式之间的所有换行符

我第一次发现了它,它教会了我如何在两种模式之间搜索

sed -e '/begin/,/end/{s/begin/replacement/p;d}'
然后我找到了一个方法来帮助删除文件中的所有换行符

sed ':a;N;$!ba;s/\n/ /g'
我试图将这两个答案结合起来,得出以下结论:

sed -e '/begin/,/end/{:a;N;$!ba;s/\n/ /p;d}'
然而,这并不完全有效。它将替换从正确行开始的换行符,但会一直持续到文件末尾。下面给出了一个例子:

Sed命令:

sed -e '/Seven/,/Fifteen/{:a;N;$!ba;s/\n/ /g}' input.txt
input.txt:

One Two Three
Four Five Six
Seven Eight Nine
Ten Eleven Twelve
Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One
输出:

One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Nineteen Twenty Twenty-One
我真正想要的是:

One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One

谢谢你的帮助

您需要将
$
更改为
/十五/

sed -e '/Seven/,/Fifteen/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt

  • $!ba=>如果不是最后一行,跳转到
    a
  • /十五/!ba=>如果不匹配,则跳转到
    a
可以缩短命令的长度:

sed '/Seven/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt

您需要将
$
更改为
/十五/

sed -e '/Seven/,/Fifteen/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt

  • $!ba=>如果不是最后一行,跳转到
    a
  • /十五/!ba=>如果不匹配,则跳转到
    a
可以缩短命令的长度:

sed '/Seven/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt

sed是一个非常好的工具,用于在一行上进行简单的替换,但对于任何其他内容(即,除了s、g和p以及-n之外的任何涉及语言构造的内容),只需使用awk即可

将GNU awk用于多字符RS、
\
字边界和gensub():

$gawk-vrs='^$'-vrs='{
匹配($0,/\.\/)
打印子文件($0,1,RSTART-1)\
gensub(/\n/,“”,“,”g“,substr($0,RSTART,RLENGTH))\
substr($0,RSTART+RLENGTH)
}"档案"
一二三
四五六
789101112131415
161718
1921年

毫不夸张地说,所有那些神秘的sed单字符语言结构(N、b、a等)在20世纪70年代中期就已经过时了,当时awk被发明,人们不再需要使用sed进行多行编辑。

sed是一个很好的工具,它可以在一行上进行简单的替换,但也可以用于其他任何操作(也就是说,除了s、g、p和-n之外,任何涉及语言结构的东西)只需使用awk即可

将GNU awk用于多字符RS、
\
字边界和gensub():

$gawk-vrs='^$'-vrs='{
匹配($0,/\.\/)
打印子文件($0,1,RSTART-1)\
gensub(/\n/,“”,“,”g“,substr($0,RSTART,RLENGTH))\
substr($0,RSTART+RLENGTH)
}"档案"
一二三
四五六
789101112131415
161718
1921年

毫不夸张地说,所有那些神秘的sed单字符语言结构(N、b、a等)实际上在20世纪70年代中期就已经过时了,当时awk被发明,人们不再需要使用sed进行多行编辑。

您也可以使用这种
sed
方法

sed '/Seven/{:loop ; N ;/\nSixteen/{p;d}; s/\n/ /g; t loop}' filename

您也可以使用此
sed
方法

sed '/Seven/{:loop ; N ;/\nSixteen/{p;d}; s/\n/ /g; t loop}' filename

下面是一个
awk
verison:

awk '/Seven/ && !g {f=1;g=1} /Fifteen/ {f=0} {printf "%s%s",$0,(f?FS:RS)}' file
One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One

下面是gnu awk的
version(单词边界):


下面是一个
awk
verison:

awk '/Seven/ && !g {f=1;g=1} /Fifteen/ {f=0} {printf "%s%s",$0,(f?FS:RS)}' file
One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One

下面是gnu awk的
version(单词边界):


由于您正在控制代码块中的循环,您不需要初始地址中的
,/十五/
。请注意
/Seven/…
将在给定的示例数据中匹配两次,第一次与预期匹配,但也与
Seven
匹配。这永远不会与以下
Seven
匹配,因此将以文件结尾和
N
命令。如果对上述命令进行改进,可能会产生意外的结果,
/\/
可能会更安全。由于您控制代码块中的循环,您不需要初始地址中的
,/十五/
。请注意,
/Seven/..
将在给定的示例数据中匹配两次,即first与预期一致,但也与
17
匹配。这与以下
15
不匹配,因此以文件结尾和
N
命令终止。因为如果改进上述命令,可能会产生意外的结果,
/\/
可能更安全。+1 wrt
printf“%s”(f?FS:RS),$0
,虽然它在本例中的行为与预期相同,但请注意,如果FS或RS包含
%
字符,它将失败。它更安全,而且更清晰,因为它将分隔符移动到打印的$0之后,以写入
printf“%s%s”,$0,(f?FS:RS)
。在非呆滞状态下,您可以使用
/(^[^[^[:alnum:])]_]|$)/
而不是
/\/
,因此您不必编写
/Seven/&&!/Seven[[:alnum:]/&&!/[:alnum:]]Seven/
Benjamin-上述解决方案与我发布的解决方案的主要区别在于,如果输入文件中有七个,但没有十五个,它们的行为会如何。我的将不做任何更改,而Jotne的将在文件末尾之前用七后面的空格替换所有换行符。显然,idk是自您没有指定。@EdMorton我同意最好使用
“%s%s”,$0,(f?FS:RS)
,但要使
FS
RS
包含
%
,您需要设置它。正确。但我不完全确定我是否理解您的观点。我只是说,如果您必须将FS或RS设置为包含
%
以匹配您的数据,则使用该语法将失败,这是不使用它的另一个原因(除了清晰之外)。我尝试过这些解决方案,它们确实有效。现在我真正知道的是RegEx,而不是sed或awk。说实话,我不知道如何解释上面的任何awk代码。我想真正学习这些工具,所以我很欣赏基于awk的答案,但我已经将基于sed的答案标记为答案,因为这就是问题的答案已被询问。+1 wrt
printf“%s”(f?FS:RS),$0
,但它将在本例中按预期运行