Get rid of whitespace on otherwise empty lines

17

2

Ah, yet another of my selfish uses of this Stack.

Being a Chromebook owner, I'm a frequent user of the Ace IDE, the editor used by Cloud9. It has lots of tools for dealing with excess whitespace, but it notably lacks one: clearing empty lines.

Your mission today is, given an input from a place I can copy-paste to [;)], output something identical, save all spaces and tabulators on otherwise empty lines.

I'll give some examples, with #s representing whitespace characters to be removed.


INPUT 1:

if (this.Color !== 'blue') {
##
  this.Color = 'blue';
}

OUTPUT:

if (this.Color !== 'blue') {
[empty line]
  this.Color = 'blue';
}

INPUT 2:

function outputSomething(times) {
  for (var iter = 0; iter < times; iter++) {
    console.log('"# # " represents a tabulator');
    // This is a comment
# # 
}}

OUTPUT:

function outputSomething(times) {
  for (var iter = 0; iter < times; iter++) {
    console.log('"# # " represents a tabulator');
    // This is a comment
[empty line]
}}

INPUT 3:

var x = 'Do you prefer spaces or tabs?';
var y = 'I\'m using both here. Sue me.';
# # ####
console.log(x + ' ' + y);

OUTPUT:

var x = 'Do you prefer spaces or tabs?';
var y = 'I\'m using both here. Sue me.';
[empty line]
console.log(x + ' ' + y);

You may process the input however you like. Output wherever, so long as I can copy-paste from it [;)].

Standard loopholes apply, shortest answer in bytes wins!

Papayaman1000

Posted 2017-04-26T13:39:18.933

Reputation: 603

Do we have to leave an empty line where it says [empty line], or no line at all? – Leaky Nun – 2017-04-26T13:40:31.790

6Oh, and, before anyone does it, no getting into the 'spaces vs tabulators' holy war. Doing that gets your answers nuked with a 10,000 byte penalty :P – Papayaman1000 – 2017-04-26T13:40:36.340

@LeakyNun an empty line, save for a newline character. – Papayaman1000 – 2017-04-26T13:40:56.933

What does # in your examples mean? – Leaky Nun – 2017-04-26T13:41:16.363

@LeakyNun # is visible shorthand for a space, while # with a space in front of it is for a tabulator. – Papayaman1000 – 2017-04-26T13:42:06.833

So the line in INPUT 3 is [space][tab][tab][space][space][space]? – Leaky Nun – 2017-04-26T13:42:58.870

@LeakyNun [tab][tab][space][space][space][space]. – Papayaman1000 – 2017-04-26T13:44:05.797

1And are all these clarifications necessary? Just nuke spaces and tabulators on lines that have no other characters. – Papayaman1000 – 2017-04-26T13:44:37.260

Is a trailing newline in the output ok? – Business Cat – 2017-04-26T13:49:54.187

@BusinessCat Yes. – Papayaman1000 – 2017-04-26T13:50:30.143

Is it okay to nuke other whitespace charcters as well? – HyperNeutrino – 2017-04-26T13:51:19.023

@HyperNeutrino Absolutely! I was mainly restricting it to ASCII to account for languages that can only process such. – Papayaman1000 – 2017-04-26T13:52:23.070

1Can we assume that the input will not contain trailing whitespace on any lines (except the all-whitespace ones, obviously)? None of the examples do. – ETHproductions – 2017-04-26T14:26:47.830

1If a line containing non-whitespace has trailing whitespace, is it ok to strip that whitespace? – Digital Trauma – 2017-04-26T15:42:58.813

@DigitalTrauma I suppose, why not. – Papayaman1000 – 2017-04-26T15:54:15.407

perhaps, this answer may interest you? https://meta.stackexchange.com/a/294870/300395 @Papayaman1000 this will let you put tabs in

– Rohan Jhunjhunwala – 2017-04-26T20:16:16.117

@mathjunkie The challenge could be called "make empty lines empty." – Esolanging Fruit – 2017-04-27T00:09:44.630

Answers

15

Japt, 10 8 6 5 4 bytes

mx1R

Try it online!

Explanation

(from the Japt docs)
.m(f,s=""):
Splits this with s, maps each item by f, then rejoins with s.

So mx1R splits the string by R which is a newline, trims the right hand side of each line using x1 and joins the strings again with a newline.

Saved 2 bytes thanks to ETHproductions.

Tom

Posted 2017-04-26T13:39:18.933

Reputation: 3 078

1Congratulations! You out-golfed Retina! – Leaky Nun – 2017-04-26T14:12:02.480

Very nice! You can save another byte with ®x1}R. – ETHproductions – 2017-04-26T14:12:43.460

Scratch that, you can just do mx1R to solve the whole problem in 4 bytes of ASCII :-) (The x1 is automatically interpreted by m as _x1} – ETHproductions – 2017-04-26T14:14:17.970

@ETHproductions Oh wow, thanks for the tips. Can't see why mx1R would work, but it's cool that it does! – Tom – 2017-04-26T14:18:33.410

It's a sort of hidden feature of Japt: whenever there's a method call that accepts a function as its first argument, and you only do one operator/method call in that function, e.g. m@Xx}, you can just use the letter/operator, e.g. mx. This also works with arguments, hence why m@Xx1} can be shortened to mx1. – ETHproductions – 2017-04-26T14:21:47.207

4

But this trims all whitespaces at the right end of a line.

– Leaky Nun – 2017-04-26T14:24:22.653

@LeakyNun You're right; none of the examples had trailing whitespaces so I assumed there wouldn't be any. – Tom – 2017-04-26T14:27:52.627

23

Retina, 5 bytes

%G`\S

Try it online!

A not so obvious approach rewards us with a better score :)

Explanation

G indicates this as a Grep stage, keeping only those lines where a match to the regex given (\S, matches non-space characters) can be found. If it wasn't for the starting % this would completely remove lines instead of just "emptying" them.

The % is a modifier which applies the stage once to each line and then joins the results with newlines: in our case this means that the empty string returned by Grep for whitespace-only lines will become an empty line in the result.

Leo

Posted 2017-04-26T13:39:18.933

Reputation: 8 482

Was just about to post this, nice. :) – Martin Ender – 2017-04-26T14:28:10.703

I guess I still have many to learn about Retina. – Leaky Nun – 2017-04-26T14:49:38.467

17

sed, 6 bytes

/\S/!g

Try it online!

/  /!  # If the line doesn't contain...
 \S    # anything non-whitespace (i.e. the entire line is whitespace)
     g #   replace the pattern space with the hold space which is empty

Riley

Posted 2017-04-26T13:39:18.933

Reputation: 11 345

2I probably would have used a substitution. Using a plain match and g was a clever way to save a couple of bytes. – Digital Trauma – 2017-04-26T15:40:14.613

1@DigitalTrauma That was my first solution. This saved 1 byte. – Riley – 2017-04-26T16:17:34.703

1Too bad sed doesn't have \S or "something that is not whitespace". Or does it? /\S/!g – aragaer – 2017-04-27T22:38:40.250

@aragaer There is! Nice! – Riley – 2017-04-27T22:51:28.013

9

JavaScript (ES6), 26 bytes

I don't understand why this is getting so many upvotes!

s=>s.replace(/^\s+$/gm,``)

Try It

f=
s=>s.replace(/^\s+$/gm,``)
i.addEventListener("input",_=>o.innerText=f(i.value))
<textarea id=i></textarea><pre id=o>

Shaggy

Posted 2017-04-26T13:39:18.933

Reputation: 24 623

9

V, 5, 4 bytes

ÇÓ/D

Try it online!

Explanation:

Ç       " On every line not matching the following regex:
 Ó/     "   a non-whitespace character...
   D    "   Delete the whole line

Hexdump:

00000000: c7d3 2f44                                ../D

James

Posted 2017-04-26T13:39:18.933

Reputation: 54 537

Are you sure that's only 5? V often uses more than 1 byte per character. – Papayaman1000 – 2017-04-26T15:13:35.040

1@papayamam1000 V never uses more than one byte per character. Right here it uses the Latin1 encoding, where all of those non-ASCII symbols are one byte. I've added a hexdump – James – 2017-04-26T15:18:33.333

very well, so it is. – Papayaman1000 – 2017-04-26T15:26:23.150

"a non-whitespace character" how does this not exempt linew with multiple whitespace chars from deletion? – Adám – 2017-06-27T22:39:38.337

7

Python 3, 63 55 36 bytes

lambda s:[x.strip()and x for x in s]

Input and output are arrays of strings. Join on '\n'.

For the original program that I/O's strings:

lambda s:'\n'.join(x.strip()and x for x in s.split('\n'))

Try it online!

Saved 8 bytes thanks to @Rod!
Saved 19 bytes thanks to @LeakyNun!

HyperNeutrino

Posted 2017-04-26T13:39:18.933

Reputation: 26 575

@LeakyNun Oh hm, forgot that I could do that. Thanks! – HyperNeutrino – 2017-04-26T14:10:25.860

2I think your original code was more in tune with the challenge. It asks for you to be able to copy paste text into an input, so really your code should take a single string, not array, and split it. – Notts90 supports Monica – 2017-04-26T16:33:12.370

6

CJam, 18 16 bytes

qN/{_" 	"-\e&N}%

Note that the string contains 1 space and 1 tab.

Try it online!

Explanation

q                 e# Read the input
 N/               e# Split it on newlines
   {              e# Apply this block to each line:
    _             e#  Copy the line
     "  "-        e#  Remove all spaces and tabs from the copy
          \       e#  Bring the original to the top of the stack
           e&     e#  Logical AND; returns the original line if the copy is truthy 
                  e#    (non-empty), otherwise returns the copy line
             N    e#  Push a newline after the line
              }%  e# (end of block)

Business Cat

Posted 2017-04-26T13:39:18.933

Reputation: 8 927

5

Retina, 8 bytes

m`^\s+$

A really pointless challenge. m makes it multiline (ignores newline). \s matches both space and tab.

Try it online!

Leaky Nun

Posted 2017-04-26T13:39:18.933

Reputation: 45 011

Retina is always first. Even while its poster is asking for [questionably necessary] clarifications in the comments. – Papayaman1000 – 2017-04-26T13:45:25.353

@Papayaman1000 People do that all the time. Then they can change their answers if the rules turn out to be different from what's expected. – HyperNeutrino – 2017-04-26T13:50:51.643

The Perl version, for 2 more bytes: s;^\d+$; (there is a final newline and -p flag)

– Dada – 2017-04-26T13:54:25.353

6Tha challenge may not be very interesting, but calling it really pointless seems excessive – Luis Mendo – 2017-04-26T14:03:29.003

@LuisMendo you can edit my wording as you see fit. – Leaky Nun – 2017-04-26T14:03:42.520

5It's your wording, and only you know the intent of your words. Editing it or not, and which new wording to use, is entirely your decision – Luis Mendo – 2017-04-26T14:06:38.313

3@HyperNeutrino the correct course of action is to close the challenge as unclear and reopen it once those clarifications have been added. – Martin Ender – 2017-04-26T14:47:55.583

@MartinEnder Okay. I think it's clear enough now. – HyperNeutrino – 2017-04-26T14:49:29.347

5

APL (Dyalog), 11 10 bytes

'\s+$'⎕R''

⎕R is an operator which derives a function which replaces stuff. In this case, anything matched by the RegEx is replaced with an empty string.

Adám

Posted 2017-04-26T13:39:18.933

Reputation: 37 779

5

Vim, 20 18 16 13 10 bytes

I am by no means a Vim expert, but this question needs a Vim answer.

:%s/^\s*$<cr>

<cr> is a carriage return.

Changelog:

  • :norm instead of :normal (-2 bytes)
  • Switching to * instead of + means we will match already empty lines, but that doesn't matter. And now we can get rid of \v (very magic option) (-2 bytes)
  • New approach: Instead of replacing every line that matches with an empty line, we replace every line that doesn't have a no non-whitespace characters with an empty line. (-3 bytes)
  • Actually, a normal replacement is shorter (thanks, @DJMcMayhem) (-3 bytes)

L3viathan

Posted 2017-04-26T13:39:18.933

Reputation: 3 151

1This is shorter as a substitute command: :%s/^\s*$<cr> – James – 2017-04-26T15:06:42.007

5

AWK, 12 11 bytes

!NF{$0=""}1

Try it online!

I was just feeling like AWK should have an answer too

It works by:

  1. Checking if there are no fields in the input. AWK by default uses all whitespace as separator between fields
  2. If there are no fields, change the input line to an empty string
  3. Print the line. As 1 is a truthy value, it runs the default command which is printing the line

jmriego

Posted 2017-04-26T13:39:18.933

Reputation: 381

Removed one byte as the semicolon is not necessary after the curly bracket – jmriego – 2017-04-27T08:08:45.780

you gave me an idea ... ^^ I reverted this and end up with 2 bytes: 'NF' – Olivier Dulac – 2017-04-27T11:34:15.880

ow... I thought we had to get rid of empty lines... :( – Olivier Dulac – 2017-04-27T11:44:24.677

1I did exactly the same as my first try and for the same reason. I know that feel :) – jmriego – 2017-04-27T12:43:34.277

the good news is : now I know how to simply get rid of those in my own programs (or when displaying a file) with a really tiny awk oneliner ^^. Your answer is good and tight, by the way. Well done. – Olivier Dulac – 2017-04-27T14:13:01.783

4

Ruby, 22 bytes

->s{s.gsub /^\s+$/,''}

Straightforward regex solution

Flambino

Posted 2017-04-26T13:39:18.933

Reputation: 1 001

3

Java 7, 57 bytes

String c(String s){return s.replaceAll("(?m)^\\s+$","");}

Explanation:

String c(String s){     // Method with String parameter and String return-type
  return s.replaceAll(  //  Return the input String after we've replaced
    "(?m)^\\s+$",       //  all lines only containing whitespaces
    "");                //  with empty Strings
                        //    (NOTE: `(?m)` enables multiline regex)
}                       // End of method

Test code:

Try it here.

class M{
  static String c(String s){return s.replaceAll("(?m)^\\s+$","");}

  public static void main(String[]a){
    System.out.println(c("if (this.Color !== 'blue') {\n \t\n  this.Color = 'blue';\n}"));
    System.out.println();
    System.out.println(c("function outputSomething(times) {\n  for (var iter = 0; iter < times; iter++) {\n    console.log('\"# # \" represents a tabulator');\n    // This is a comment\n  \t\n}}"));
    System.out.println();
    System.out.println(c("var x = 'Do you prefer spaces or tabs?';\nvar y = 'I\'m using both here. Sue me.';\n    \t\t\t \nconsole.log(x + ' ' + y);"));
  }
}

Kevin Cruijssen

Posted 2017-04-26T13:39:18.933

Reputation: 67 575

2

Groovy, 31 bytes

{it.replaceAll(/\n\s+\n/,"\n")}

Magic Octopus Urn

Posted 2017-04-26T13:39:18.933

Reputation: 19 422

Won't that remove the empty line? – Shaggy – 2017-04-28T10:29:48.940

1

Perl 6,  15  12 bytes

15

{S:g/^^\h+$$//}

Try it

{         # bare block lambda with implicit parameter 「$_」

  S       # string replace (implicitly against 「$_」)
  :global # globally
  /
    ^^    # match beginning of line
      \h+ # match at least one horizontal whitespace
    $$    # match end of line

  //      # replace with nothing
}

11+1

perl6 -pe 's/^^\h+$$//'

Largely the same as above.

  • -p runs the code for every line of input, putting the line into $_ and printing whatever is left in $_.
  • s replaces in-place, whereas S returns the result.
  • No need for :g/:global as -p takes care of that.

Brad Gilbert b2gills

Posted 2017-04-26T13:39:18.933

Reputation: 12 713

1

Python 2, 26 bytes

lambda l:map(str.rstrip,l)

Try it online! Inputs and outputs a list of strings.

This takes advantage of the ruling in the comments that trailing whitespace may be removed on non-empty lines.

xnor

Posted 2017-04-26T13:39:18.933

Reputation: 115 687

1

Vim, 13 9 bytes

:v/\S/le↵

Edits:

  • Original answer: :v/\S/d↵ (based on this vim question on SO).
    It deletes empty lines, which isn't the expected behavior.

  • Valid answer using vglobal: :v/\S/norm D↵

  • Now using the left-align ex command instead of normal D

Morgan

Posted 2017-04-26T13:39:18.933

Reputation: 111

Welcome to PPCG! I'm not really sure why you apologized, because this is a valid answer on its own. – Mego – 2017-04-28T07:11:03.037

Thank you! It expands on @L3viathan's answer and uses the same "language", so i'd have commented on his solution to limit the (already large) number of answers if I could. – Morgan – 2017-04-28T07:18:21.587

We aren't terribly concerned with having a lot of answers, or having multiple solutions in the same language. While we do encourage comments instead of new answers for small improvements upon existing answers, it's still OK to post a new answer (especially given that you can't comment yet). – Mego – 2017-04-28T07:19:52.060

0

C, 168 bytes

#define P putchar(*t++)
s;e(char*t){s=0;while(*t>10)if(*t!=32|*t!=9)return 0;else t++,s++;return s;}
r(char*t){while(*t==10)P;if(!*t)return;if(!e(t))while(*t)P;t+=e(t);}

Detailed

#include <stdio.h>

int e (char * t)
{
    int s = 0;

    // till the end of the line
    while (*t!='\0' && *t!='\n')
        // if it's not a space
        if (*t!=' ' || *t!='    ')
            // ignore the line
            return 0;
        else
            // count the space
            t++, s++;

    // return number of spaces
    return s;
}

void r (char * t)
{
    // skip to empty lines
    while (*t != '\0' && *t == '\n') putchar('\n'), t++;

    // stop at end of string
    if (*t == '\0') return;

    // if there is contnet print it
    if (!e(t)) while(*t != '\0') putchar(*t), t++;

    // skip to the end of line
    t += e(t);
}

int main (int argc, char**argv)
{
    if (argc > 1) r(argv[1]);
    putchar('\n');
    return 0;
}

Khaled.K

Posted 2017-04-26T13:39:18.933

Reputation: 1 435

0

C, 100 bytes

c,i,j;f(char*s){for(i=j=c=0;s[i];s[++j]^10?c=s[j]^32:(printf(!c?"\n":"%.*s",j-i+1,s+i),c=0,i=j+1));}

See it work online.

2501

Posted 2017-04-26T13:39:18.933

Reputation: 748

0

QuadR, 5 bytes

\s+$

Try it online!

\s+ replace one or more whitespace chars followed by
$ end of line

 with nothing

Adám

Posted 2017-04-26T13:39:18.933

Reputation: 37 779