tags:

views:

15384

answers:

9

I unsuccesfully tried:

sed 's#/\n# #g' file
sed 's#^$# #g' file

How to fix it?

+21  A: 

Use tr instead?

tr '\n' ' ' < input
dmckee
I cannot understand why sed cannot do it. Please, clarify to use different tool.
Masi
+1 for solving the problem with another tool
Masi
Sed is line-based therefore it is hard for it to grasp newlines.
Alexander Gladysh
Alexander: Does "stream editor" mean line-based? Perhaps, the name is confusing.
Masi
sed works on a "stream" of input, but it comprehends it in newline delimited chunks. It is a unix tool, which means it does one thing very well. The one thing is "work on a file line-wise". Making it do something else will be hard, and risks being buggy. The moral of the story is: choose the right tool. A great many of your questions seem to take the form "How can I make this tool do something it was never meant to do?" Those questions are interesting, but if they come up in the course of solving a real problem, you're probably doing it wrong.
dmckee
Useless use of `cat`.
Dennis Williamson
*"Useless use of cat"* Yeah. Fixed. And I should know better too...
dmckee
+5  A: 

The perl version works the way you expected.

perl -i -p -e 's/\n//' file

Edit: As pointed out in the comments, it's worth noting that this edits in place. -i.bak will give you a backup of the original file before the replacement in case your regex isn't as smart as you thought.

ire_and_curses
Please at least mention that `-i` without a suffix makes *no backup*. `-i.bak` protects you from an easy, ugly mistake (say, forgetting to type `-p` and zeroing out the file).
Telemachus
@Telemachus: It's a fair point, but it can be argued either way. The main reason I didn't mention it is that the sed example in the OP's question doesn't make backups, so it seems superfluous here. The other reason is that I've never actually used the backup functionality (I find automatic backups annoying, actually), so I always forget it's there. The third reason is it makes my command line four characters longer. For better or worse (probably worse), I'm a compulsive minimalist; I just prefer brevity. I realise you don't agree. I will try my best to remember to warn about backups in future.
ire_and_curses
@Ire_and_curses: Actually, you just made a damn good argument for ignoring me. That is, you have reasons for your choices, and whether or not I agree with the choices, I certainly respect that. I'm not sure entirely why, but I've been on a tear about this particular thing lately (the `-i` flag in Perl without a suffix). I'm sure I'll find something else to obsess about soon enough. :)
Telemachus
@ire_and_curses: I just checked, and I hadn't realized that I've bothered *you* in particular about this twice in the last two or three days. Time for me to let go of this particular issue and go for a walk, I think.
Telemachus
@Telemachus: No problem. I've edited the answer for posterity. Hope you enjoyed the walk. ;)
ire_and_curses
+5  A: 

I'm not an expert, but I guess in sed you'd first need to append the next line into the pattern space, bij using "N". From the section "Multiline Pattern Space" in "Advanced sed Commands" of the book sed & awk (Dale Dougherty and Arnold Robbins; O'Reilly 1997; page 107 in the preview):

The multiline Next (N) command creates a multiline pattern space by reading a new line of input and appending it to the contents of the pattern space. The original contents of pattern space and the new input line are separated by a newline. The embedded newline character can be matched in patterns by the escape sequence "\n". In a multiline pattern space, the metacharacter "^" matches the very first character of the pattern space, and not the character(s) following any embedded newline(s). Similarly, "$" matches only the final newline in the pattern space, and not any embedded newline(s). After the Next command is executed, control is then passed to subsequent commands in the script.

From man sed:

[2addr]N

Append the next line of input to the pattern space, using an embedded newline character to separate the appended material from the original contents. Note that the current line number changes.

I've used this to search (multiple) badly formatted log files, in which the search string may be found on an "orphaned" next line.

Arjan
+1 for good refences.
Masi
One reference is a bit illegal though... Buy the book! ;-)
Arjan
Ok, now that that link has been removed: is there any policy on that? And would we also close topics discussing all kind of things that may be illegal in some countries?
Arjan
+25  A: 

Or use this solution with sed:

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

This will read the whole file in a loop, then replaces the newline(s) with a space.

Update: explanation.

  1. create a register via :a
  2. append the current and next line to the register via N
  3. if we are before the last line, branch to the created register $!ba (`$! means not to do it on the last line (as there should be one final newline)).
  4. finally the substitution replaces every newline with a space on the pattern space (which is the contents of the a register = the whole file.
Zsolt Botykai
I cannot verify this is correct, but +1 for being able to understand it ;-)
Arjan
Very cool. I found my first command that works in Ubuntu but not in Mac.
Masi
+1 for explanations and solving the original question.
Masi
Although the tr-tool is probably the best way to go, I must accept your question because it solves the question.
Masi
@Masi, so you get different output on a Mac? Mac OS X surely knows the `sed` command; I'd be a bit disappointed if the output differs.
Arjan
@Arjan and Masi: OS X uses BSD's `sed` rather than GNU `sed`, so there may be some subtle (and some not so subtle) differences in the two. This is a constant pain if you work on both OS X and *nix machines. I usually install GNU's `coreutils` and `findutils` on OS X, and ignore the BSD versions.
Telemachus
Arjan: It does Not work with Mac. It does not change the file, at all.
Masi
Dennis Williamson
A: 

@OP, if you want to replace newlines in a file, you can just use dos2unix (or unix2dox)

dos2unix yourfile yourfile
ghostdog74
+2  A: 

The answer with the :a register ...

http://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-n/1252191#1252191

... does not work in freebsd 7.2 on the command line:

( echo foo ; echo bar ) | sed ':a;N;$!ba;s/\n/ /g'
sed: 1: ":a;N;$!ba;s/\n/ /g": unused label 'a;N;$!ba;s/\n/ /g'
foo
bar

But does if you put the sed script in a file or use -e to "build" the sed script...

> (echo foo; echo bar) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g'
foo bar

or ...

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

Maybe the sed in OS X is similar.

Juan
A: 

Hi,

How can I use perl like the above example to replace two lines in a row that only contain a carriage return, followed by a string, such as "123456abcdefg"?

There are two blank lines at the top of the file, followed by the string I've listed above. I want to delete the first blank line of the file, and replace the second with a new string, terminated by the third. Unless there's a specific way to only operate on the first two lines of a file.

IOW, I'm trying to do:

perl -pi.orig -e 's/^\n\n123456abcdefg$/NewString\n123456abcefg/mg' filename

but, alas, it doesn't work. What am I missing? Am I making it too complicated? :-)

Thanks, Alex

alex
you should start a new question.
ghostdog74
A: 

On Mac OS X (using FreeBSD sed):

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta
bashfu
A: 

who needs sed. bash:

cat test.txt |  while read line; do echo -n "$line "; done
pike