17
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ Do we have to leave an empty line where it says [empty line], or no line at all? \$\endgroup\$ – Leaky Nun Apr 26 '17 at 13:40
  • 6
    \$\begingroup\$ Oh, 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 \$\endgroup\$ – Papayaman1000 Apr 26 '17 at 13:40
  • 1
    \$\begingroup\$ And are all these clarifications necessary? Just nuke spaces and tabulators on lines that have no other characters. \$\endgroup\$ – Papayaman1000 Apr 26 '17 at 13:44
  • 1
    \$\begingroup\$ Can we assume that the input will not contain trailing whitespace on any lines (except the all-whitespace ones, obviously)? None of the examples do. \$\endgroup\$ – ETHproductions Apr 26 '17 at 14:26
  • 1
    \$\begingroup\$ If a line containing non-whitespace has trailing whitespace, is it ok to strip that whitespace? \$\endgroup\$ – Digital Trauma Apr 26 '17 at 15:42

20 Answers 20

15
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Congratulations! You out-golfed Retina! \$\endgroup\$ – Leaky Nun Apr 26 '17 at 14:12
  • \$\begingroup\$ Very nice! You can save another byte with ®x1}R. \$\endgroup\$ – ETHproductions Apr 26 '17 at 14:12
  • \$\begingroup\$ 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} \$\endgroup\$ – ETHproductions Apr 26 '17 at 14:14
  • \$\begingroup\$ @ETHproductions Oh wow, thanks for the tips. Can't see why mx1R would work, but it's cool that it does! \$\endgroup\$ – Tom Apr 26 '17 at 14:18
  • 4
    \$\begingroup\$ But this trims all whitespaces at the right end of a line. \$\endgroup\$ – Leaky Nun Apr 26 '17 at 14:24
23
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Was just about to post this, nice. :) \$\endgroup\$ – Martin Ender Apr 26 '17 at 14:28
  • \$\begingroup\$ I guess I still have many to learn about Retina. \$\endgroup\$ – Leaky Nun Apr 26 '17 at 14:49
17
\$\begingroup\$

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
\$\endgroup\$
  • 2
    \$\begingroup\$ I probably would have used a substitution. Using a plain match and g was a clever way to save a couple of bytes. \$\endgroup\$ – Digital Trauma Apr 26 '17 at 15:40
  • 1
    \$\begingroup\$ @DigitalTrauma That was my first solution. This saved 1 byte. \$\endgroup\$ – Riley Apr 26 '17 at 16:17
  • 1
    \$\begingroup\$ Too bad sed doesn't have \S or "something that is not whitespace". Or does it? /\S/!g \$\endgroup\$ – aragaer Apr 27 '17 at 22:38
  • \$\begingroup\$ @aragaer There is! Nice! \$\endgroup\$ – Riley Apr 27 '17 at 22:51
9
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Are you sure that's only 5? V often uses more than 1 byte per character. \$\endgroup\$ – Papayaman1000 Apr 26 '17 at 15:13
  • 1
    \$\begingroup\$ @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 \$\endgroup\$ – DJMcMayhem Apr 26 '17 at 15:18
  • \$\begingroup\$ very well, so it is. \$\endgroup\$ – Papayaman1000 Apr 26 '17 at 15:26
  • \$\begingroup\$ "a non-whitespace character" how does this not exempt linew with multiple whitespace chars from deletion? \$\endgroup\$ – Adám Jun 27 '17 at 22:39
9
\$\begingroup\$

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>

\$\endgroup\$
7
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ @LeakyNun Oh hm, forgot that I could do that. Thanks! \$\endgroup\$ – HyperNeutrino Apr 26 '17 at 14:10
  • 2
    \$\begingroup\$ I 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. \$\endgroup\$ – Notts90 Apr 26 '17 at 16:33
6
\$\begingroup\$

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)
\$\endgroup\$
5
\$\begingroup\$

Retina, 8 bytes

m`^\s+$

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

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Retina is always first. Even while its poster is asking for [questionably necessary] clarifications in the comments. \$\endgroup\$ – Papayaman1000 Apr 26 '17 at 13:45
  • \$\begingroup\$ @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. \$\endgroup\$ – HyperNeutrino Apr 26 '17 at 13:50
  • 6
    \$\begingroup\$ Tha challenge may not be very interesting, but calling it really pointless seems excessive \$\endgroup\$ – Luis Mendo Apr 26 '17 at 14:03
  • 5
    \$\begingroup\$ It'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 \$\endgroup\$ – Luis Mendo Apr 26 '17 at 14:06
  • 3
    \$\begingroup\$ @HyperNeutrino the correct course of action is to close the challenge as unclear and reopen it once those clarifications have been added. \$\endgroup\$ – Martin Ender Apr 26 '17 at 14:47
5
\$\begingroup\$

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)
\$\endgroup\$
  • 1
    \$\begingroup\$ This is shorter as a substitute command: :%s/^\s*$<cr> \$\endgroup\$ – DJMcMayhem Apr 26 '17 at 15:06
5
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Removed one byte as the semicolon is not necessary after the curly bracket \$\endgroup\$ – jmriego Apr 27 '17 at 8:08
  • \$\begingroup\$ you gave me an idea ... ^^ I reverted this and end up with 2 bytes: 'NF' \$\endgroup\$ – Olivier Dulac Apr 27 '17 at 11:34
  • \$\begingroup\$ ow... I thought we had to get rid of empty lines... :( \$\endgroup\$ – Olivier Dulac Apr 27 '17 at 11:44
  • 1
    \$\begingroup\$ I did exactly the same as my first try and for the same reason. I know that feel :) \$\endgroup\$ – jmriego Apr 27 '17 at 12:43
  • \$\begingroup\$ 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. \$\endgroup\$ – Olivier Dulac Apr 27 '17 at 14:13
5
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

Ruby, 22 bytes

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

Straightforward regex solution

\$\endgroup\$
3
\$\begingroup\$

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);"));
  }
}
\$\endgroup\$
2
\$\begingroup\$

Groovy, 31 bytes

{it.replaceAll(/\n\s+\n/,"\n")}
\$\endgroup\$
  • \$\begingroup\$ Won't that remove the empty line? \$\endgroup\$ – Shaggy Apr 28 '17 at 10:29
1
\$\begingroup\$

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.
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! I'm not really sure why you apologized, because this is a valid answer on its own. \$\endgroup\$ – Mego Apr 28 '17 at 7:11
  • \$\begingroup\$ 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. \$\endgroup\$ – Morgan Apr 28 '17 at 7:18
  • \$\begingroup\$ 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). \$\endgroup\$ – Mego Apr 28 '17 at 7:19
0
\$\begingroup\$

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;
}
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

QuadR, 5 bytes

\s+$

Try it online!

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

 with nothing

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.