-4
\$\begingroup\$

Given text, remove leading and trailing whitespace (spaces, tabs, and newlines).

Alternate title: Implement your own string trimming.

Input

ASCII text (printable + spaces, tabs (\t), and newlines (\n)), in whatever format you would like. Carriage returns (\r) are outside of the scope of the input.

Output

The same text in the same format, but with (only) trailing and leading spaces, tabs, and newlines removed.

*Note: If your language naturally outputs a trailing space/newline, please note that in your answer.

Test Cases

This test case ensures that you can handle \s and the like. Please note whitespace in it.

Input

 \s test \t\n
 

Output

\s test \t\n

For the following test cases (but not the above), \s is space, \t is tab, \n is newline. => splits input and output.

\s\t\n\s => (empty string)

\stest\s => test

\nt\n\st\t => t\n\st

_ => _

\s\s\n\s1\s+\s1\n => 1\s+\s1

||_\s => ||_

No builitins allowed that trim either specific characters or given characters. Builtins that remove arbitrary characters from the beginning/end of a string, or that remove given characters from any position in a string (by default) are allowed.

\$\endgroup\$
7
  • 1
    \$\begingroup\$ It's not exactly clear what you mean by no built-ins. Is regex allowed? \$\endgroup\$
    – DJMcMayhem
    May 20, 2017 at 16:11
  • \$\begingroup\$ Maybe you mean that a trimming function removes a substring from both sides of a string? \$\endgroup\$ May 20, 2017 at 16:19
  • \$\begingroup\$ @StephenS Yeah that's what I mean. \$\endgroup\$ May 20, 2017 at 16:21
  • \$\begingroup\$ How about trimming by an integer amount (rather than "remove occurrence of this character"), dequeuing (removing the first item), popping (removing the last item), rotating, splitting? \$\endgroup\$ May 20, 2017 at 16:22
  • \$\begingroup\$ Why would dequeue not be allowed? How is s[1:] trimming? \$\endgroup\$
    – Dennis
    May 20, 2017 at 16:36

10 Answers 10

3
\$\begingroup\$

Retina, 10 bytes

^\s+|\s+$

Try it online!

Trailing newline is added automatically and is unavoidable.

\$\endgroup\$
4
  • \$\begingroup\$ Retina can do better. I'm really tempted to post it as a separate answer though. \$\endgroup\$
    – Neil
    May 20, 2017 at 17:07
  • 1
    \$\begingroup\$ @Neil go ahead. \$\endgroup\$
    – Leaky Nun
    May 20, 2017 at 17:08
  • \$\begingroup\$ Never mind, found a bug in my answer. \$\endgroup\$
    – Neil
    May 20, 2017 at 17:09
  • \$\begingroup\$ might be shorter to use matching with something like: (\S.+?)\s+ \$\endgroup\$
    – Downgoat
    May 20, 2017 at 17:48
1
\$\begingroup\$

Jelly, 8 bytes

>⁶TṬo\Tị

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Baby, vanilla baby ;) \$\endgroup\$
    – Okx
    May 20, 2017 at 16:27
  • 1
    \$\begingroup\$ Character comparisons work?! \$\endgroup\$ May 20, 2017 at 16:28
  • \$\begingroup\$ @JonathanAllan Why would they not? Integers and character have the same depth. \$\endgroup\$
    – Dennis
    May 20, 2017 at 16:39
  • \$\begingroup\$ I just seem to recall them not working. \$\endgroup\$ May 20, 2017 at 16:41
  • 1
    \$\begingroup\$ @JonathanAllan You probably recall trying to compare strings. That won't work since > vectorizes. \$\endgroup\$
    – Dennis
    May 20, 2017 at 16:45
1
\$\begingroup\$

JS (ES6), 27 bytes

i=>i.replace(/^\s+|\s+$/g,"")
\$\endgroup\$
1
\$\begingroup\$

Carrot, 21 bytes

#^//\S([\s\S]*\S)?/gS

Try it online!

Explanation

Carrot has several global variables, one for each type: string, float and array. The program starts in string-mode, where all the operators will affect the global string variable. And I call these variables the "stack".

#^                     Set the stack-string to the value of all of the input
/                      Get matches of this regex:
 /\S([\s\S]*\S)?/g
                       And set the stack-array to the array containing these matches
                       There will only ever be one or zero matches
S                      Convert to string-mode by joining the elements of the array

The S operator is supposed to take a string or number as an argument to join the array on, but apparently it is not needed in this case (I don't understand why).

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

Jelly, 11 8 bytes

-2 bytes thanks to Dennis (use direct character conversion, similar to his answer O>32 -> >⁶
-1 byte thanks to Dennis (removing a redundant quick)

>⁶TṂr$Ṁị

Try it online!

Steering clear of anything that could be considered "trimming".

How?

>⁶TṂr$Ṁị - Main link: list of characters (a.k.a. string)  e.g. "  t xt  "
 ⁶       - literal space character
>        - greater than (vectorises)                           [0,0,1,0,1,1,0,0]
  T      - truthy indexes                                      [    3,  5,6    ]
     $   - last two links as a monad
   Ṃ     -   minimum                                                3
    r    -   inclusive range                                   [[3],[3,4,5],[3,4,5,6]]
      Ṁ  - maximum                                             [3,4,5,6]
       ị - index into the input                                 "t xt"
\$\endgroup\$
1
  • 1
    \$\begingroup\$ >⁶TṂr$Ṁị works too. \$\endgroup\$
    – Dennis
    May 20, 2017 at 16:31
0
\$\begingroup\$

PHP, 40 Bytes

Regex Version

<?=preg_replace("#^\s+|\s+$#","",$argn);

Try it online!

PHP, 77 Bytes

The Regex version was so boring so I would try it without a Regex

<?=substr($a=$argn,strspn($a,$c="\t\n "),-strspn(strrev($a),$c)?:strlen($a));

Try it online!

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

C (gcc) & preprocessor, 152 149 bytes

#define f(x)(x==32|x==9|x==10)
char*t(char*o){int i=strlen(o);for(;--i>0;){if(!f(o[i]))break;o[i]=0;};while(1){if(f(*o))o=o+1;else break;}return o;}

-3 bytes: Ironically, I forgot to remove my spaces.

A function that takes in a char* (pointer to the first character of the string (how C implements strings)), and returns a pointer to the first non-space character in the string, and also replaces all trailing spaces with null bytes, C's string terminator.

Ungolfed:

#define isspace(x) (x==32|x==9|x==10) 
// save bytes by not using this whole thing each time
// (32 is ' ', 9 is '\t', 10 is '\n')
char *trim(char *original) {
    int i=strlen(original);
    for(;--i>0;){                   // start at the end of the string, work backwards
        if(!isspace(original[i]))
            break;              // if the character not is a space character, stop working backwards
        original[i]=0;          // else: replace the character with a null byte, C's string terminator
    }
    while(1){
        if(isspace(original[0]))// shift the pointer until the first char is not a space
            original = original + 1;
        else break;
    }
    return original;            // return the modified pointer
}
\$\endgroup\$
0
\$\begingroup\$

Japt, 9 bytes

e"^%s|%s$

Try it online (-Q flag used for visualisation only)

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

C#, 60 bytes

s=>System.Text.RegularExpressions.Replace(s,"^\s+|\s+$","");

If I could use built-ins this is only 12 bytes:

s=>s.Trim();
\$\endgroup\$
0
\$\begingroup\$

Python 2, 44 bytes

lambda s:re.sub(r'^\s*|\s*$','',s)
import re

Try it online!

Non-regex: 62 bytes

Takes input as list of characters. Outputs by reference.

def f(s):exec'while s[%s].isspace():del s[%s]\n'*2%(0,0,-1,-1)
\$\endgroup\$

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