71

I have input.txt

1
2
3
4
5

I need to get such output.txt

1,2,3,4,5

How to do it?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
vinnitu
  • 4,234
  • 10
  • 41
  • 59
  • What line ending should the output have? You mention CR\LF in the question - you mean that you have a DOS text file? And the output should be a DOS text file (so you need a final CRLF)? – Jonathan Leffler Jan 04 '11 at 14:40

9 Answers9

112

Try this:

tr '\n' ',' < input.txt > output.txt
eumiro
  • 207,213
  • 34
  • 299
  • 261
  • 1
    This deals with the newlines; what about the carriage returns? There might be nothing to do if the user is on DOS and it is a text file - the input routines convert CRLF to '\n'. More seriously, perhaps, the code replaces the final newline (CRLF) with a comma. – Jonathan Leffler Jan 04 '11 at 14:38
  • 39
    This solution leaves a comma at the end: – Nestor Urquiza Sep 09 '15 at 18:41
  • 1
    just as a reply to Jonathon's question, I had to replace `'\n'` with `'\r'` for carriage return. – TravisF Jun 28 '17 at 01:32
  • 1
    If you have both `\r` and `\n` in there, you can use `dos2unix` to strip carriage returns and then apply this `tr` for `\n`s. – NikoNyrh Aug 22 '17 at 11:52
  • This simple command just saved me a bunch of time by converting the output of one SQL query into CSV instead of using an subquery with an `IN` statement :) – Justin Jenkins Mar 05 '19 at 04:26
  • @NestorUrquiza This is because of the POSIX rule of what a line is: _A sequence of zero or more non- characters plus a terminating character._ (See [this](https://stackoverflow.com/questions/729692)). Hence this is not the best answer. Your [answer](https://stackoverflow.com/a/32487078/8344060) using `paste` overcomes this. – kvantour Oct 15 '19 at 13:47
25

With sed, you could use:

sed -e 'H;${x;s/\n/,/g;s/^,//;p;};d'

The H appends the pattern space to the hold space (saving the current line in the hold space). The ${...} surrounds actions that apply to the last line only. Those actions are: x swap hold and pattern space; s/\n/,/g substitute embedded newlines with commas; s/^,// delete the leading comma (there's a newline at the start of the hold space); and p print. The d deletes the pattern space - no printing.

You could also use, therefore:

sed -n -e 'H;${x;s/\n/,/g;s/^,//;p;}'

The -n suppresses default printing so the final d is no longer needed.

This solution assumes that the CRLF line endings are the local native line ending (so you are working on DOS) and that sed will therefore generate the local native line ending in the print operation. If you have DOS-format input but want Unix-format (LF only) output, then you have to work a bit harder - but you also need to stipulate this explicitly in the question.

It worked OK for me on MacOS X 10.6.5 with the numbers 1..5, and 1..50, and 1..5000 (23,893 characters in the single line of output); I'm not sure that I'd want to push it any harder than that.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
20

In response to @Jonathan's comment to @eumiro's answer:

tr -s '\r\n' ',' < input.txt | sed -e 's/,$/\n/' > output.txt
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
13

Use paste command. Here is using pipes:

echo "1\n2\n3\n4\n5" | paste -s -d, /dev/stdin

Here is using a file:

echo "1\n2\n3\n4\n5" > /tmp/input.txt
paste -s -d, /tmp/input.txt

Per man pages the s concatenates all lines and d allows to define the delimiter character.

Nestor Urquiza
  • 2,821
  • 28
  • 21
13

tr and sed used be very good but when it comes to file parsing and regex you can't beat perl (Not sure why people think that sed and tr are closer to shell than perl... )

perl -pe 's/\n/$1,/' your_file

if you want pure shell to do it then look at string matching

${string/#substring/replacement}
Luke
  • 11,426
  • 43
  • 60
  • 69
Arnaud
  • 345
  • 1
  • 11
  • +1 because tr replaces all the characters so was no good for me and the sed solution worked if you cat a file but failed for some reason if you `tail -f` a file – MikeKulls Oct 05 '20 at 01:46
12
  • Awk versions:
    • awk '{printf("%s,",$0)}' input.txt
    • awk 'BEGIN{ORS=","} {print $0}' input.txt
    • Output - 1,2,3,4,5,

Since you asked for 1,2,3,4,5, as compared to 1,2,3,4,5, (note the comma after 5, most of the solutions above also include the trailing comma), here are two more versions with Awk (with wc and sed) to get rid of the last comma:

  • i='input.txt'; awk -v c=$(wc -l $i | cut -d' ' -f1) '{printf("%s",$0);if(NR<c){printf(",")}}' $i

  • awk '{printf("%s,",$0)}' input.txt | sed 's/,\s*$//'

gsbabil
  • 7,505
  • 3
  • 26
  • 28
4
printf "1\n2\n3" | tr '\n' ','

if you want to output that to a file just do

printf "1\n2\n3" | tr '\n' ',' > myFile

if you have the content in a file do

cat myInput.txt | tr '\n' ',' > myOutput.txt
Tono Nam
  • 34,064
  • 78
  • 298
  • 470
2
  • python version:

    python -c 'import sys; print(",".join(sys.stdin.read().splitlines()))'

Doesn't have the trailing comma problem (because join works that way), and splitlines splits data on native line endings (and removes them).

Community
  • 1
  • 1
qneill
  • 1,643
  • 14
  • 18
0
cat input.txt | sed -e 's|$|,|' | xargs -i echo "{}"
Luke
  • 11,426
  • 43
  • 60
  • 69
Noel Yap
  • 18,822
  • 21
  • 92
  • 144