0

I would like to search through a file and find all instances where the last non-blank character is a comma and move the line below that up one. Essentially, undoing line continuations like

private static final double SOME_NUMBERS[][] = {
    {1.0, -6.032174644509064E-23},
    {-0.25, -0.25},
    {-0.16624879837036133, -2.6033824355191673E-8}
};

and transforming that to

private static final double SOME_NUMBERS[][] = {
    {1.0, -6.032174644509064E-23}, {-0.25, -0.25}, {-0.16624879837036133, -2.6033824355191673E-8}
};

Is there a good way to do this?

mjswartz
  • 715
  • 1
  • 6
  • 19
  • Have you tried anything for this? This should, assuming you don't have any ranges/etc. in which to apply this and don't have any lines that you *don't* want this applied to, be a fairly simple `sed` or `awk` script. – Etan Reisner Nov 09 '15 at 17:33
  • I would think doing something like `sed s/,\n/ /g` (conceptually) would work, but I'm pretty novice with sed. Also, this only would work for `,\n` and not `, \n` and I would like it to handle any amount of spaces between `,` and `\n` – mjswartz Nov 09 '15 at 17:36
  • 1
    Other then that `sed` works on a line-by-line basis and so can't match `\n` like that (by default), yes. – Etan Reisner Nov 09 '15 at 17:37

4 Answers4

2

As mjswartz suggests in the comments, we need a sed substitution command like s/,\n/ /g. That, however, does not work by itself because, by default, sed reads in only one line at a time. We can fix that by reading in the whole file first and then doing the substitution:

$ sed 'H;1h;$!d;x; s/,[[:blank:]]*\n[[:blank:]]*/, /g;' file
private static final double SOME_NUMBERS[][] = {
    {1.0, -6.032174644509064E-23}, {-0.25, -0.25}, {-0.16624879837036133, -2.6033824355191673E-8}
};

Because this reads in the whole file at once, this is not a good approach for huge files.

The above was tested with GNU sed.

How it works

  • H;1h;$!d;x;

    This series of commands reads in the whole file. It is probably simplest to think of this as an idiom. If you really want to know the gory details:

    • H - Append current line to hold space
    • 1h - If this is the first line, overwrite the hold space with it
    • $!d - If this is not the last line, delete pattern space and jump to the next line.
    • x - Exchange hold and pattern space to put whole file in pattern space
  • s/,[[:blank:]]*\n[[:blank:]]*/, /g

    This looks for lines that end with a comma, optionally followed by blanks, followed by a newline and replaces that, and any leading space on the following line, with a comma and a single space.

John1024
  • 109,961
  • 14
  • 137
  • 171
  • This looks like it replaces the commas whereas I would like to keep them. What would I tweak to get `,\n` to turn into `, `? Sorry if that was not clear – mjswartz Nov 09 '15 at 19:16
  • @mjswartz Thanks for spotting that. It is fixed: the solution now keeps commas. – John1024 Nov 09 '15 at 19:26
2

I think for large files awk would be better:

awk -vRS=", *\n" -vORS=", " '1' file
0

On lua-shell, just write like this:

function nextlineup()
    vim:normal("j^y$k$pjddk")
end

vim:open("code.txt")
vim:normal("G")
while vim:k() do
    vim:normal("$") 
    if(vim.currc == string.byte(',')) nextlineup();
end

If you are not familier with vim ,this script seems a bit scary and not robust. In fact, every operation in it is precise(and much quicker, because tey are built-in functions). Since you are processing a code file, i suggest you try it.

here is a demo

weiweishuo
  • 847
  • 7
  • 15
0

Here is a perl solution.
cat file | perl -e '{$c = 0; while () { s/^\s+/ / if ($c); s/,\s*$/,/; print($_); $c = (m/,\s*$/) ? 1: 0; }}'

balabhi
  • 641
  • 5
  • 5