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\texample string

Chris
źródło
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
5
Możliwy duplikat przycinania łańcucha w Pythonie
Breno Baiardi

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
James Thompson
źródło
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
gcb
źródło
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"
ars
źródło
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.

Lucas
źródło
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 ']
Robert King
źródło
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.

użytkownik1149913
źródło
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)
MaK
źródło
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”

Safvan CK
źródło
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

pbn
źródło
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"

morgansmnm
źródło
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, )_(, [email protected], ,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, )_(, [email protected], ,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,  [email protected], 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, )_(, [email protected], ,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, )_(, [email protected], ,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

skrzypek Joshuy
źródło
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'
海洋 顶端
źródło
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.

J L
źródło
-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.

Mayur Koshti
źródło
-2

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

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

wynik:

ATGCGACACGATCGACC
Mistrz Roshi
źródło
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"
Rafe
źródło
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,