A good way to make long strings wrap to newline?
Asked Answered
B

9

67

In my project, I have a bunch of strings that are read in from a file. Most of them, when printed in the command console, exceed 80 characters in length and wrap around, looking ugly.

I want to be able to have Python read the string, then test if it is over 75 characters in length. If it is, then split the string up into multiple strings, then print one after the other on a new line. I also want it to be smart, not cutting off full words. i.e. "The quick brown <newline> fox..." instead of "the quick bro<newline>wn fox...".

I've tried modifying similar code that truncates the string after a set length, but just trashes the string instead of putting it in a new line.

What are some methods I could use to accomplish this?

Baxie answered 7/5, 2013 at 23:22 Comment(2)
textwrap is great for this, but it depends on the format of your file! Is the file a bunch of strings together, or are they on separate lines, because on separate lines, when you use textwrap it will most likely get wonkyDiffuse
@Ryan-Saxe it's a text file with each string separated by a set character (a pipe, |). textwrap sounds like it would work, then!Baxie
T
116

You could use textwrap module:

>>> import textwrap
>>> strs = "In my project, I have a bunch of strings that are read in from a file. Most of them, when printed in the command console, exceed 80 characters in length and wrap around, looking ugly."
>>> print(textwrap.fill(strs, 20))
In my project, I
have a bunch of
strings that are
read in from a file.
Most of them, when
printed in the
command console,
exceed 80 characters
in length and wrap
around, looking
ugly.

help on textwrap.fill:

>>> textwrap.fill?

Definition: textwrap.fill(text, width=70, **kwargs)
Docstring:
Fill a single paragraph of text, returning a new string.

Reformat the single paragraph in 'text' to fit in lines of no more
than 'width' columns, and return a new string containing the entire
wrapped paragraph.  As with wrap(), tabs are expanded and other
whitespace characters converted to space.  See TextWrapper class for
available keyword args to customize wrapping behaviour.

Use regex if you don't want to merge a line into another line:

import re


strs = """In my project, I have a bunch of strings that are.
Read in from a file.
Most of them, when printed in the command console, exceed 80.
Characters in length and wrap around, looking ugly."""

print('\n'.join(line.strip() for line in re.findall(r'.{1,40}(?:\s+|$)', strs)))

# Reading a single line at once:
for x in strs.splitlines():
    print '\n'.join(line.strip() for line in re.findall(r'.{1,40}(?:\s+|$)', x))

output:

In my project, I have a bunch of strings
that are.
Read in from a file.
Most of them, when printed in the
command console, exceed 80.
Characters in length and wrap around,
looking ugly.
Tobolsk answered 7/5, 2013 at 23:25 Comment(7)
@Ryan-Saxe. This is just on-the-spot logic, but how about putting a terminal character at the end of each line, reading each string into a list, then doing textwrap on each list index? There might need to be some form of character stripping after this, but it sounds like ti would work. Testing now.Baxie
@JoshuaMerriman that wouldn't work because if a line has like 90 characters, the next line would have 10Diffuse
@RyanSaxe - what I've done in my project, which may work for others, is I've read each line into an array, then set variables to the values of those arrays. therefore, it does not matter if the strings are on new lines in the source file - they will be in their own variable in the program.Baxie
@RyanSaxe I've added a regex based solution to handle that case.Tobolsk
Sometimes it's necessary to preserve words longer than the wrap width (e.g. a really long URL). You can use r'(?:\S{41,}|.{1,40})(?:\s+|$)' regex for that instead.Muna
Is there a way to get it so it will only remove the line if the line break is the ONLY thing on the line, otherwise it will wrap it? I have been able to either (1) Break all the line breaks, but not wrap the text, or (2) wrap all the text, but break all of the line breaks.Lafayette
Is it possible to add `` to ending of each line ?Linson
O
15

This is what the textwrap module is for. Try textwrap.fill(some_string, width=75).

Ocher answered 7/5, 2013 at 23:25 Comment(0)
P
7

This is similar to Ashwini's answer but does not use re:

lim=75
for s in input_string.split("\n"):
    if s == "": print
    w=0 
    l = []
    for d in s.split():
        if w + len(d) + 1 <= lim:
            l.append(d)
            w += len(d) + 1 
        else:
            print " ".join(l)
            l = [d] 
            w = len(d)
    if (len(l)): print " ".join(l)

Output when the input is your question:

In my project, I have a bunch of strings that are read in from a file.
Most of them, when printed in the command console, exceed 80 characters in
length and wrap around, looking ugly.

I want to be able to have Python read the string, then test if it is over
75 characters in length. If it is, then split the string up into multiple
strings, then print one after the other on a new line. I also want it to be
smart, not cutting off full words. i.e. "The quick brown <newline> fox..."
instead of "the quick bro<newline>wn fox...".
Potful answered 8/5, 2013 at 0:25 Comment(3)
Thanks for the answer, but frankly I think using textwrap is a much better and easier manage method of wrapping text. that said, it would be good for people who want more flexibility in their line wrapping, or want to understand the logic behind textwrapping to develop their own modules!Baxie
@JoshuaMerriman Yes but that doesn't mean you have to make this the accepted answer. Accept the answer that helped you, you are correct this answer will help people who want to implement this solution by themselves but that doesn't mean we should promote reinventing the wheel. This is not a good reason to unaccepted the answer that you actually used.Kayser
Oops, did I un-accept the last answer? I was under the impression that I could accept multiple answers. I was wrong, though. Terribly sorry!Baxie
C
3
string, max_width = input(), int(input())
result = wrap(string, max_width)
print(result)

def wrap(string, max_width):
    s=''
    for i in range(0,len(string),max_width):
        s+=string[i:i+max_width]
        s+='\n'
    return s
Case answered 3/11, 2019 at 2:5 Comment(0)
I
3

In python-3

import textwrap
def wrap(string, max_width):
    return '\n'.join(textwrap.wrap(string,max_width))

Input:

wrap(ABCDEFGHIJKLIMNOQRSTUVWXYZ, 4)

output:

ABCD
EFGH
IJKL
IMNO
QRST
UVWX
YZ
Imbecile answered 8/4, 2020 at 7:31 Comment(1)
fill() is a shorthand for "\n".join(wrap(text, ...))Humblebee
D
0
string, max_width = input(), int(input())
result = wrap(string, max_width)
print(result)

def wrap(string, max_width):
    s=''
    for i in range(0,len(string),max_width):
        s=s+string[i:i+max_width]
        s=s+'\n'
    return s
Devoirs answered 18/8, 2019 at 21:1 Comment(2)
Welcome to Stack Overflow! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Flotage
This will split a proper word.Valiancy
E
0
import textwrap

def wrap(string, max_width):
    return textwrap.fill(string,max_width)

if __name__ == '__main__':
    string, max_width = input(), int(input())
    result = wrap(string, max_width)
    print(result)

input: ABCDEFGHIJKLIMNOQRSTUVWXYZ "\n" 4

output: ABCD"\n" EFGH"\n" IJKL"\n" IMNO"\n" QRST"\n" UVWX"\n" YZ"\n"

Explode answered 30/8, 2020 at 6:14 Comment(1)
Welcome to Stack Overflow! Please note you are answering a very old and already answered question. Here is a guide on How to Answer.Janiecejanifer
B
0

Without using any inbuilt function, this will wrap the string into a paragraph of input width. Given you have a long string get the length of the string, use range(0,len(string),max_width) so that it will iterate till it becomes empty. Empty string is assigning new line. One thing to note here is when you return(string[i:i:i+max_width])

def wrap(string, max_width):
    empty_string=''
    for i in range(0,len(string),max_width):
        empty_string+=string[i:i+max_width]
        print(string[i:i+max_width])
        empty_string+='\n'
    return (string[i:i:i+max_width])
    if __name__ == '__main__':
    string, max_width = input(), int(input())
    result = wrap(string, max_width)
    print(result)
Begga answered 7/4, 2022 at 11:11 Comment(0)
G
0

You can use the standard library textwrap module to wrap text in a way that:

  • does not remove blank lines
  • does not turn tabs and multiple spaces into a single space
  • starts the new line character count afresh after each newline in the original text

Here is how:

import textwrap

strs = """In my project, I have a bunch of strings that are.
Read in from a file.
Most of them, when printed in the command console, exceed 80.
Characters in length and wrap around, looking ugly."""

def wrap(s, max_width=80):
    wrapper = textwrap.TextWrapper(width=max_width, tabsize=4, replace_whitespace=False, drop_whitespace=True)
    return '\n'.join([wrapper.fill(l) for l in s.splitlines()])

print(wrap(strs, max_width=40))

Output:

In my project, I have a bunch of strings
that are.
Read in from a file.
Most of them, when printed in the
command console, exceed 80.
Characters in length and wrap around,
looking ugly.

In the function, the string is split by line (s.splitlines()) in order to start the line character count anew after each new line in the original string. This operation is suggested by the documentation (https://docs.python.org/3/library/textwrap.html#textwrap.TextWrapper.replace_whitespace).

The above example produces the exact same output as the regex option in @ashwini-chaudhary's post (accepted answer).

Grevera answered 21/6 at 1:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.