Jak przyciąć białe znaki?


1071

Czy istnieje funkcja Python, która przycina białe znaki (spacje i tabulatory) z ciągu?

Przykład: \t example string\t→example string


1
Dzięki za heads-upy. Odkryłem wcześniej funkcję paska, ale wydaje się, że nie działa na moje wejście.
— Chris

1
To samo, co: stackoverflow.com/questions/761804/trimming-a-string-in-python (nawet jeśli to pytanie jest nieco jaśniejsze, IMHO). Jest to również prawie takie samo: stackoverflow.com/questions/959215/…
— Jonik

6
Znaki python uważa, że ​​białe znaki są przechowywane w string.whitespace.
— John Fouhy

2
Przez „funkcję pasków” masz na myśli metodę pasków? „Wygląda na to, że nie działa w przypadku moich danych wejściowych” Podaj kod, dane wejściowe i wyjściowe.
— S.Lott

Odpowiedzi:


1599

Biała spacja po obu stronach:

s = "  \t a string example\t  "
s = s.strip()

Biała spacja po prawej stronie:

s = s.rstrip()

Biała spacja po lewej stronie:

s = s.lstrip()

Jak wskazuje thedz , możesz podać argument, aby usunąć dowolne znaki z dowolnej z następujących funkcji:

s = s.strip(' \t\n\r')

Będzie to rozebrać każdą przestrzeń, \t, \n, lub \rznaki z lewej strony, po prawej stronie, albo po obu stronach łańcucha.

Powyższe przykłady usuwają tylko łańcuchy z lewej i prawej strony łańcuchów. Jeśli chcesz również usunąć znaki ze środka ciągu, spróbuj re.sub:

import re
print re.sub('[\s+]', '', s)

To powinno wydrukować:

astringexample

18
strip () przyjmuje argument, aby powiedzieć mu, co się potknie. Spróbuj: strip ('\ t \ n \ r')
— thedz

3
Wyniki dla przykładów powinny być bardzo pomocne :)
— ton

4
Nie trzeba wymieniać białych znaków: docs.python.org/2/library/string.html#string.whitespace
— jesuis

3
Ostatni przykład jest dokładnie taki jak przy użyciu str.replace(" ",""). Nie musisz używać re, chyba że masz więcej niż jedno miejsce, wtedy twój przykład nie działa. []jest przeznaczony do oznaczania pojedynczych znaków, nie jest to konieczne, jeśli używasz tylko \s. Użyj jednego \s+lub [\s]+(zbędne), ale [\s+]nie wykonać zadanie, zwłaszcza jeśli chcesz zastąpić wielokrotne spacje z jednego spośród takich jak toczenie "this example" się "this example".
— Jorge E. Cardona,

3
@ JorgeE.Cardona - Jedną z rzeczy, o których się nieco mylisz - \sbędą zawierać karty, a replace(" ", "")nie będą.
— ArtOfWarfare

72

trimMetoda Python nazywa się strip:

str.strip() #trim
str.lstrip() #ltrim
str.rstrip() #rtrim

5
co jest łatwe do zapamiętania, ponieważ s tri p wygląda prawie jak tri m.
— isar

22

Dla wiodących i końcowych białych znaków:

s = '   foo    \t   '
print s.strip() # prints "foo"

W przeciwnym razie działa wyrażenie regularne:

import re
pat = re.compile(r'\s+')
s = '  \t  foo   \t   bar \t  '
print pat.sub('', s) # prints "foobar"

1
Nie skompilowałeś wyrażenia regularnego. Musisz to zrobićpat = re.compile(r'\s+')
— Evan Fosmark

Zazwyczaj chcą sub(" ", s)nie ""później będzie łączyć słowa i nie będziesz już w stanie wykorzystać .split(" ")do tokenize.
— user3467349,

fajnie byłoby zobaczyć wyniki printwypowiedzi
— Ron Klein

19

Możesz także użyć bardzo prostej i podstawowej funkcji: str.replace () , działa z białymi spacjami i kartami:

>>> whitespaces = "   abcd ef gh ijkl       "
>>> tabs = "        abcde       fgh        ijkl"

>>> print whitespaces.replace(" ", "")
abcdefghijkl
>>> print tabs.replace(" ", "")
abcdefghijkl

Proste i łatwe.


2
Ale to, niestety, usuwa również przestrzeń wewnętrzną, podczas gdy przykład w pierwotnym pytaniu pozostawia wewnętrzne przestrzenie nietknięte.
— Brandon Rhodes,

12
#how to trim a multi line string or a file

s=""" line one
\tline two\t
line three """

#line1 starts with a space, #2 starts and ends with a tab, #3 ends with a space.

s1=s.splitlines()
print s1
[' line one', '\tline two\t', 'line three ']

print [i.strip() for i in s1]
['line one', 'line two', 'line three']




#more details:

#we could also have used a forloop from the begining:
for line in s.splitlines():
    line=line.strip()
    process(line)

#we could also be reading a file line by line.. e.g. my_file=open(filename), or with open(filename) as myfile:
for line in my_file:
    line=line.strip()
    process(line)

#moot point: note splitlines() removed the newline characters, we can keep them by passing True:
#although split() will then remove them anyway..
s2=s.splitlines(True)
print s2
[' line one\n', '\tline two\t\n', 'line three ']

4

Nikt jeszcze nie opublikował tych wyrażeń regularnych.

Pasujący:

>>> import re
>>> p=re.compile('\\s*(.*\\S)?\\s*')

>>> m=p.match('  \t blah ')
>>> m.group(1)
'blah'

>>> m=p.match('  \tbl ah  \t ')
>>> m.group(1)
'bl ah'

>>> m=p.match('  \t  ')
>>> print m.group(1)
None

Wyszukiwanie (musisz inaczej traktować wielkość liter „jedyne spacje”):

>>> p1=re.compile('\\S.*\\S')

>>> m=p1.search('  \tblah  \t ')
>>> m.group()
'blah'

>>> m=p1.search('  \tbl ah  \t ')
>>> m.group()
'bl ah'

>>> m=p1.search('  \t  ')
>>> m.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

Jeśli używasz re.sub, możesz usunąć wewnętrzne białe znaki, co może być niepożądane.


3

Białe znaki obejmują spację, tabulatory i CRLF . Zatem elegancką i jednowarstwową funkcją struny, której możemy użyć jest tłumaczenie .

' hello apple'.translate(None, ' \n\t\r')

LUB jeśli chcesz być dokładny

import string
' hello  apple'.translate(None, string.whitespace)

3

(re.sub ('+', '', (my_str.replace ('\ n', '')))). strip ()

Spowoduje to usunięcie wszystkich niechcianych spacji i znaków nowej linii. Mam nadzieję, że to pomoże

import re
my_str = '   a     b \n c   '
formatted_str = (re.sub(' +', ' ',(my_str.replace('\n',' ')))).strip()

Spowoduje to:

„a b \ nc” zostanie zmienione na „ab c”


2
    something = "\t  please_     \t remove_  all_    \n\n\n\nwhitespaces\n\t  "

    something = "".join(something.split())

wynik:

please_remove_all_whitespaces


Dodanie komentarza Le Droida do odpowiedzi. Aby oddzielić spacją:

    something = "\t  please     \t remove  all   extra \n\n\n\nwhitespaces\n\t  "
    something = " ".join(something.split())

wynik:

usuń wszystkie dodatkowe białe znaki


1
Prosty i wydajny. Przydałby się znak „” .join (... aby słowa były oddzielone spacją.
— Le Droid,

1

Jeśli używasz Python 3: w instrukcji print zakończ sep = "". To oddzieli wszystkie przestrzenie.

PRZYKŁAD:

txt="potatoes"
print("I love ",txt,"",sep="")

Spowoduje to wydrukowanie: Kocham ziemniaki.

Zamiast: Kocham ziemniaki.

W twoim przypadku, ponieważ chciałbyś przejechać \ t, wykonaj sep = "\ t"


1

Po przyjrzeniu się kilku rozwiązaniom o różnym stopniu zrozumienia, zastanawiałem się, co zrobić, jeśli ciąg zostanie oddzielony przecinkiem ...

problem

Próbując przetworzyć plik CSV z danymi kontaktowymi, potrzebowałem rozwiązania tego problemu: przyciąć zbędne białe znaki i niektóre śmieci, ale zachować końcowe przecinki i wewnętrzne białe znaki. Pracując z polem zawierającym notatki o kontaktach, chciałem usunąć śmieci, pozostawiając dobre rzeczy. Przycinając wszystkie znaki interpunkcyjne i plewy, nie chciałem stracić spacji między złożonymi tokenami, ponieważ nie chciałem później odbudowywać.

Wyrażenia regularne i wzorce: [\s_]+?\W+

Wzorzec szuka pojedynczych wystąpień dowolnego znaku spacji i znaku podkreślenia („_”) od 1 do nieograniczonej liczby leniwie (możliwie jak najmniej znaków), przy [\s_]+?czym poprzedzają one znaki niebędące słowami występujące od 1 do nieograniczonej liczby znaków czas z tym: \W+(jest równoważny [^a-zA-Z0-9_]). W szczególności znajduje to fragmenty białych znaków: znaki puste (\ 0), tabulatory (\ t), znaki nowej linii (\ n), feed-forward (\ f), powrót karetki (\ r).

Zaletę tego widzę podwójnie:

  1. że nie usuwa białych znaków między pełnymi słowami / tokenami, które możesz chcieć trzymać razem;

  2. Wbudowana w Pythona metoda ciągu strip()nie obsługuje ciągu, tylko lewy i prawy koniec, a domyślnym argumentem są znaki puste (patrz poniższy przykład: kilka znaków nowej linii jest w tekście i strip()nie usuwa ich wszystkich, podczas gdy wzorzec wyrażenia regularnego robi) .text.strip(' \n\t\r')

To wykracza poza pytanie PO, ale myślę, że istnieje wiele przypadków, w których mogliśmy mieć dziwne, patologiczne wystąpienia w danych tekstowych, tak jak ja (niektóre, w jaki sposób znaki specjalne kończyły się w niektórych tekstach). Ponadto w ciągach podobnych do list nie chcemy eliminować separatora, chyba że separator oddzieli dwa białe znaki lub niektóre znaki niebędące znakami, takie jak „-,” lub „-, ,,,”.

NB: Nie mówię o ograniczniku samego CSV. Tylko przypadki w CSV, w których dane są podobne do listy, tzn. Są łańcuchem znaków podciągów cs.

Pełne ujawnienie: manipuluję tekstem przez około miesiąc, a regex tylko przez ostatnie dwa tygodnie, więc jestem pewien, że brakuje mi pewnych niuansów. To powiedziawszy, w przypadku mniejszych kolekcji ciągów (moje są w ramce danych 12 000 wierszy i 40 nieparzystych kolumn), jako ostatni krok po przejściu do usunięcia obcych znaków, działa to wyjątkowo dobrze, szczególnie jeśli wprowadzisz dodatkowe białe znaki w miejscu, w którym chcesz oddzielić tekst, do którego dołącza się znak niebędący słowem, ale nie chcesz dodawać spacji tam, gdzie wcześniej nie było.

Przykład:

import re


text = "\"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, , , , \r, , \0, ff dd \n invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, \n i69rpofhfsp9t7c practice 20ignition - 20june \t\n .2134.pdf 2109                                                 \n\n\n\nklkjsdf\""

print(f"Here is the text as formatted:\n{text}\n")
print()
print("Trimming both the whitespaces and the non-word characters that follow them.")
print()
trim_ws_punctn = re.compile(r'[\s_]+?\W+')
clean_text = trim_ws_punctn.sub(' ', text)
print(clean_text)
print()
print("what about 'strip()'?")
print(f"Here is the text, formatted as is:\n{text}\n")
clean_text = text.strip(' \n\t\r')  # strip out whitespace?
print()
print(f"Here is the text, formatted as is:\n{clean_text}\n")

print()
print("Are 'text' and 'clean_text' unchanged?")
print(clean_text == text)

To daje:

Here is the text as formatted:

"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf" 

using regex to trim both the whitespaces and the non-word characters that follow them.

"portfolio, derp, hello-world, hello-, world, founders, mentors, ffib, biff, 1, 12.18.02, 12, 2013, 9874890288, ff, series a, exit, general mailing, fr, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk,  jim.somedude@blahblah.com, dd invites,subscribed,, master, dd invites,subscribed, ff dd invites, subscribed, alumni spring 2012 deck: https: www.dropbox.com s, i69rpofhfsp9t7c practice 20ignition 20june 2134.pdf 2109 klkjsdf"

Very nice.
What about 'strip()'?

Here is the text, formatted as is:

"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf"


Here is the text, after stipping with 'strip':


"portfolio, derp, hello-world, hello-, -world, founders, mentors, :, ?, %, ,>, , ffib, biff, 1, 12.18.02, 12,  2013, 9874890288, .., ..., ...., , ff, series a, exit, general mailing, fr, , , ,, co founder, pitch_at_palace, ba, _slkdjfl_bf, sdf_jlk, )_(, jim.somedude@blahblah.com, ,dd invites,subscribed,, master, , , ,  dd invites,subscribed, ,, , , ff dd 
 invites, subscribed, , ,  , , alumni spring 2012 deck: https: www.dropbox.com s, 
 i69rpofhfsp9t7c practice 20ignition - 20june 
 .2134.pdf 2109                                                 



klkjsdf"
Are 'text' and 'clean_text' unchanged? 'True'

Tak więc pasek usuwa po jednym spacji. Więc w przypadku PO strip()jest w porządku. ale jeśli sytuacja stanie się bardziej złożona, wyrażenie regularne i podobny wzór mogą mieć pewną wartość dla bardziej ogólnych ustawień.

zobacz to w akcji


0

spróbuj przetłumaczyć

>>> import string
>>> print '\t\r\n  hello \r\n world \t\r\n'

  hello 
 world  
>>> tr = string.maketrans(string.whitespace, ' '*len(string.whitespace))
>>> '\t\r\n  hello \r\n world \t\r\n'.translate(tr)
'     hello    world    '
>>> '\t\r\n  hello \r\n world \t\r\n'.translate(tr).replace(' ', '')
'helloworld'

0

Jeśli chcesz przyciąć białe znaki tylko na początku i na końcu łańcucha, możesz zrobić coś takiego:

some_string = "    Hello,    world!\n    "
new_string = some_string.strip()
# new_string is now "Hello,    world!"

Działa to bardzo podobnie do metody Qt QString :: trimmed (), ponieważ usuwa początkowe i końcowe białe spacje, pozostawiając wewnętrzne białe spacje w spokoju.

Ale jeśli chcesz czegoś takiego jak metoda QString :: uproszczona () Qt, która nie tylko usuwa wiodące i końcowe białe spacje, ale także „wyrównuje” wszystkie kolejne wewnętrzne białe spacje do jednego znaku spacji, możesz użyć kombinacji .split()i " ".join, w ten sposób:

some_string = "\t    Hello,  \n\t  world!\n    "
new_string = " ".join(some_string.split())
# new_string is now "Hello, world!"

W tym ostatnim przykładzie każda sekwencja wewnętrznych białych znaków została zastąpiona pojedynczą spacją, wciąż przycinając białe znaki na początku i na końcu łańcucha.


-1

Ogólnie używam następującej metody:

>>> myStr = "Hi\n Stack Over \r flow!"
>>> charList = [u"\u005Cn",u"\u005Cr",u"\u005Ct"]
>>> import re
>>> for i in charList:
        myStr = re.sub(i, r"", myStr)

>>> myStr
'Hi Stack Over  flow'

Uwaga: służy tylko do usuwania „\ n”, „\ r” i „\ t”. Nie usuwa dodatkowych spacji.


-2

do usuwania białych znaków ze środka łańcucha

$p = "ATGCGAC ACGATCGACC";
$p =~ s/\s//g;
print $p;

wynik:

ATGCGACACGATCGACC

1
to pytanie dotyczy python, a nie Javascript czy perl
— phuclv,

-17

Spowoduje to usunięcie wszystkich białych znaków i znaków nowej linii zarówno na początku, jak i na końcu łańcucha:

>>> s = "  \n\t  \n   some \n text \n     "
>>> re.sub("^\s+|\s+$", "", s)
>>> "some \n text"

8
Po co używać wyrażenia regularnego, kiedy s.strip()dokładnie to robi?
— Ned Batchelder

1
s.strip()obsługuje tylko początkowe białe znaki, ale nie „odkrywa” białych znaków po usunięciu innych niechcianych znaków. Pamiętaj, że spowoduje to usunięcie nawet spacji po ostatnim prowadzeniu\n
— Rafe

Ktoś zlekceważył tę odpowiedź, ale nie wyjaśnił, dlaczego jest ona wadliwa. Wstydź się (@NedBatchelder, jeśli głos był negatywny, proszę cofnąć, ponieważ wyjaśniłem twoje pytanie i nie wspomniałeś o niczym, co faktycznie zostało złamane z moją odpowiedzią)
— Rafe

10
Rafe, możesz chcieć dwukrotnie sprawdzić: s.strip()daje dokładnie taki sam wynik jak wyrażenie regularne.
— Ned Batchelder,

3
@Rafe, mylisz to z wykończeniem. Strip wykonuje wymagane operacje.
— iMitwe,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.