0

I have a CSV file that contains data like so:

1, 2, 3
A, B, C
4, 5, 6

I'm trying to output this in bash as a single string separated by newlines like so:

"1, 2, 3\nA, B, C\n4, 5, 6"

I tried numerous ways but nothing has worked yet. Thanks for your help!

EDIT:

Based on answers provided, since other users of my code might need the same transformation and I can't guarantee what's on their system, still looking for answers independent of whether or not I have:

  1. GNU sed installed
  2. Windows line endings or not
  3. Have dos2unix installed
Frankie
  • 11,508
  • 5
  • 53
  • 60
  • Since I can't even answer my own question... here's what ultimately worked for me: `var=$(tr '\r\n' '\\n' < input.csv)` Then `echo "$var:q" > output.txt` – Frankie Nov 24 '19 at 18:30

2 Answers2

3

I'm unsure whether you want to use your expected output in bash or want to use the specified output somewhere else. Here are two answers for both cases:

Replacing newlines with \n and add surrounding " quotes

In this case your question is a duplicate – at least the part of replacing newlines with literal \ns. The easiest solution is sed -z 's/\n/\\n/g;s/.*/"&"/' yourFile provided that you have GNU sed.
If your file ends with a newline (as text files usually do) so will your string:
"1, 2, 3\nA, B, C\n4, 5, 6\n"

If you don't want that trailing \n you can exclude it before the actual processing:

sed -z 's/\n$//;s/\n/\\n/g;s/.*/"&"/' yourFile
"1, 2, 3\nA, B, C\n4, 5, 6"

Encode a multi-line file in a single-line bash string

Use bash's built-in printf with the %q format. From help printpf:

%q quote the argument in a way that can be reused as shell input

To pass the file content to printf use a subshell:

printf %q "$(< yourFile)"

This will use bash's C-string format since \n is not treated as a newline in double quoted "..." strings:

$'1, 2, 3\nA, B, C\n4, 5, 6'
Socowi
  • 25,550
  • 3
  • 32
  • 54
  • Unfortunately, the first option gave me `sed: illegal option -- z` and the second option gave me `1,2,3$'\r'$'\n'A,B,C$'\r'$'\n'4,5,6%`. Sorry I don't quite understand! – Frankie Nov 22 '19 at 18:42
  • The error shows that you don't have GNU sed but another version instead. The second output shows that your file does not use linux line endings `\n` but windows line endings `\r\n`. Convert your file to linux line endings (use the `dos2unix` tool) and then use the marked duplicate to replace `\n` with `\\n` **or** use `sed 's/\r/\\n/' yourFile | tr -d '\n'`. – Socowi Nov 22 '19 at 21:37
1

Both of these questions take exactly the same approach to accomplish this task.

It should just be a matter of swapping the "," out for a literal "\n", which you can do with \\n

EDIT: In the event the links go dead, the relevant solution from the previous answers is below. Full credit to Zsolt Botykai for this answer, which I've modified for your specific use case:

Use this solution with GNU sed:

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

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

Explanation:

  1. Create a label via :a.
  2. Append the current and next line to the pattern space via N.
  3. If we are before the last line, branch to the created label $!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 whole file).
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/24660543) – shalomb Nov 22 '19 at 19:11
  • Excellent point, thanks for pointing this out @shalomb! I've modified my answer to include the relevant parts of the answer from the provided links. – David Allewell Nov 22 '19 at 23:52
  • @DavidAllewell unfortunately this just gave me the exact same output as the table I originally had. – Frankie Nov 23 '19 at 01:03
  • @Frankie Really? I get the requested result. Can you show a terminal output? What version of Bash are you using (I'm presuming Bash). Are there any carriage returns in the CSV file, perhaps? – David Allewell Nov 23 '19 at 12:10