OSX s换行符-为什么可以将空格转换为换行符,但不能将换行符转换为空格 [英] OSX sed newlines - why conversion of whitespace to newlines works, but newlines are not converted to spaces

查看:72
本文介绍了OSX s换行符-为什么可以将空格转换为换行符,但不能将换行符转换为空格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OSX上的

有一些怪癖.此资源( http://nlfiedler.github.io/2010/12/05/newlines-in-sed-on-mac.html )包含有关如何将空格转换为换行符的信息:

  echo'foo bar baz quux'|sed -e's//\'$'\ n/g' 

OR(@ghoti的建议确实使它更易于阅读):

  echo'foo bar baz quux'|sed -e $'s//\\\ n/g' 

但是,当我尝试反向操作时-将换行符转换为空格,则不起作用:

  echo -e"foo \ nbar" |sed -e's/\'$'\ n//g' 

仅更改 \ n 的更直接的方法也不起作用:

  echo -e"foo \ nbar" |sed -e's/\ n//g' 

这里有一个相关的答案: https://superuser.com/questions/307165/newlines-in-sed-on-mac-os-x ,并附有Spiff的详细回答(在页面末尾),但是应用相同的逻辑并不能解决问题.

这是在OSX上起作用的一种方式(通过http://www.benjiegillam.com/2011/09/using-sed-to-replace-newlines/):

  sed -e':a'-e'N'-e'$!ba'-e's/\ n//g' 

但是,我仍然很好奇为什么逆转原始方法不起作用.

更新:这是使它与两行一起工作的方法(解决方案是使用 N 嵌入换行符):

  echo -e"foo \ nbar \ n" |sed -e'N; s/\ n//g' 

替代解决方案(有关详细说明,请参阅@ghoti的完整答案):

  echo -e"foo \ nbar \ n" |sed -n'1h; 2,$ H; $ {; x; s/\ n//gp;}' 

但是,此解决方案似乎比问题声明中建议的解决方案慢一点(注意这些命令的顺序很重要,因此尝试以不同的顺序对其进行测试可能很有意义):

 时间序列10000 |sed -n'1h; 2,$ H; $ {; x; s/\ n//gp;}'>/dev/空时间序列10000 |sed -e':a'-e'N'-e'$!ba'-e's/\ n//g'>/dev/空 

解决方案

您的问题似乎是为什么[将空格转换为换行符]的原始方法不可行?".

在 sed 中,换行符与其说是行的一部分,不如说是记录分隔符.考虑 $ ,即模式空间末尾的null,它位于该行的最后一个字符之后,而不是每行的换行符.

使用换行符的sed命令,例如 H N 甚至 s ,都超出了newline-as-record-的范围,分隔器.您要替换的记录在换行符之间.

为了替换换行符,您需要使用 N H 等在模式空间内获取换行符.

所以这是一个选择.

  printf'foo \ nbar \ nbaz \ n'|sed -n'1h; 2,$ H; $ {; x; s/\ n//gp;}' 

这个想法是,我们将所有行追加到保持缓冲区,然后在文件末尾,将保持缓冲区移回模式空间以进行替换,并立即用空格替换换行符./p>

1h; 2,$ H 的构造避免了在输出的开头出现空白,这是由于在 H 的每行数据之前附加了换行符而引起的.

sed on OSX has some quirks. This resource (http://nlfiedler.github.io/2010/12/05/newlines-in-sed-on-mac.html) contains information on how to convert whitespace into a newline:

 echo 'foo bar baz quux' | sed -e 's/ /\'$'\n/g'

OR (@ghoti's suggestion which does make it easier to read):

echo 'foo bar baz quux' |  sed -e $'s/ /\\\n/g'

However, when I try the reverse - converting newlines to whitespace, it doesn't work:

echo -e "foo\nbar" | sed -e 's/\'$'\n/ /g'

A more straightforward approach of just changing \n doesn't work either:

echo -e "foo\nbar" | sed -e 's/\n/ /g'

There's a related answer here: https://superuser.com/questions/307165/newlines-in-sed-on-mac-os-x, with a detailed answer by Spiff (right at the end of the page), however applying the same logic didn't resolve the problem.

Here's one way that does work on OSX (via http://www.benjiegillam.com/2011/09/using-sed-to-replace-newlines/):

 sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'

However, I am still curious why reversing the original approach doesn't work.

UPDATE: here's how to make it work with two lines (the solution is to use N to embed the newline characters):

echo -e "foo\nbar\n" | sed -e 'N;s/\n/ /g'

AN ALTERNATIVE SOLUTION (see full answer by @ghoti for detailed explanation):

echo -e "foo\nbar\n" | sed -n '1h;2,$H;${;x;s/\n/ /gp;}'

However, this solution appears to be a tiny bit slower than the one suggested in the question statement (note order of these commands matters, so it might make sense to try testing them in different orders):

time seq 10000 | sed -n '1h;2,$H;${;x;s/\n/ /gp;}' > /dev/null

time seq 10000 | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' > /dev/null

解决方案

Your question appears to be "why doesn't the reverse of the original approach [of converting spaces to newlines] work?".

In sed, the newline is more of a record separator than part of the line. Consider that $, the null at the end of the pattern space, comes after the last character of the line, and is not a newline of every line.

Sed commands that utilize newlines, like H and N and even s, do so outside the scope of newline-as-record-separator. The records you're substituting are between the newlines.

In order to substitute a newline, then, you need to get it INSIDE the pattern space, using N, H, etc.

So here's an option.

printf 'foo\nbar\nbaz\n' | sed -n '1h;2,$H;${;x;s/\n/ /gp;}'

The idea is that we'll append all our lines to the hold buffer, then at the end of the file, move the hold buffer back to the pattern space for substitution, and replace the newlines with spaces all at once.

The 1h;2,$H construction avoids a blank at the beginning of your output, caused by the newline that is appended before each line of data with H.

这篇关于OSX s换行符-为什么可以将空格转换为换行符,但不能将换行符转换为空格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆