python進階:第三章(字符串處理)

問題一:如何拆分含有多種分隔符的字符串?

問題內容:
我們要把某個字符串依據分隔符號拆分不同的字段村缸,該字段包含多種不同的分隔符,例如:
s = 'ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz'
其中的 , | ; \t 都是分隔符號,如何處理怒医?

對于單一的分隔符:

In [4]: x = !ps  aux 

In [5]: s = x[-1] 

In [6]: s 
Out[6]: 'root     32487  0.0  0.0      0     0 ?        S    09:44   0:01 [kworker/u24:0]'

In [7]: s.split?
Docstring:
S.split(sep=None, maxsplit=-1) -> list of strings

Return a list of the words in S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
Type:      builtin_function_or_method

In [8]: s.split() 
Out[8]: 
['root',
 '32487',
 '0.0',
 '0.0',
 '0',
 '0',
 '?',
 'S',
 '09:44',
 '0:01',
 '[kworker/u24:0]']

解決方案:
方法一:連續(xù)使用str.split()方法,每次處理一個分隔符號奢讨。
方法二:使用正則表達式的re.split()方法稚叹,一次性拆分字符串。

方法一:

In [9]: s = 'ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz'

In [10]: s.split(';') 
Out[10]: ['ab', 'cd|efg|hi,jkl|mn\topq', 'rst,uvw\txyz']

In [11]: res = s.split(';') 

In [12]: map(lambda x: x.split('|'),res) 
Out[12]: <map at 0x7f2faa12bc50>

In [13]: list(map(lambda x: x.split('|'),res)) 
Out[13]: [['ab'], ['cd', 'efg', 'hi,jkl', 'mn\topq'], ['rst,uvw\txyz']]

In [14]: t = [] 

In [38]: list(map(lambda x: t.extend(x.split('|')),res))
Out[38]: [None, None, None]

In [39]: t
Out[39]: ['ab', 'cd', 'efg', 'hi,jkl', 'mn\topq', 'rst,uvw\txyz']

In [40]: res = t 

In [41]: t = [] 

In [42]: list(map(lambda x: t.extend(x.split(',')),res))
Out[42]: [None, None, None, None, None, None]

In [43]: t
Out[43]: ['ab', 'cd', 'efg', 'hi', 'jkl', 'mn\topq', 'rst', 'uvw\txyz']

根據上面的邏輯,我們可以寫個函數(shù)

In [44]: def mySplit(s,ds):
    ...:     res = [s] 
    ...:     for d in ds:
    ...:         t = [] 
    ...:         list(map(lambda x: t.extend(x.split(d)),res))
    ...:         res = t 
    ...:     return res 
    ...: 

In [45]: s = 'ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz' 

In [46]: mySplit(s,';,|\t') 
Out[46]: ['ab', 'cd', 'efg', 'hi', 'jkl', 'mn', 'opq', 'rst', 'uvw', 'xyz']

但是有兩個分隔符連續(xù)的時候就會生成空的字符串

In [47]: s = 'ab;;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz' 

In [48]: mySplit(s,';,|\t') 
Out[48]: ['ab', '', 'cd', 'efg', 'hi', 'jkl', 'mn', 'opq', 'rst', 'uvw', 'xyz']

我們修改函數(shù)扒袖,當字符串不為空的時候才返回

In [49]: def mySplit(s,ds):
    ...:     res = [s] 
    ...:     for d in ds:
    ...:         t = [] 
    ...:         list(map(lambda x: t.extend(x.split(d)),res))
    ...:         res = t 
    ...:     return [x  for x in res if x ] 
    ...:      
    ...: 

In [50]: s = 'ab;;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz' 

In [51]: mySplit(s,';,|\t') 
Out[51]: ['ab', 'cd', 'efg', 'hi', 'jkl', 'mn', 'opq', 'rst', 'uvw', 'xyz']

方法二:

In [56]: import re 

In [57]: re.split?
Signature: re.split(pattern, string, maxsplit=0, flags=0)
Docstring:
Split the source string by the occurrences of the pattern,
returning a list containing the resulting substrings.  If
capturing parentheses are used in pattern, then the text of all
groups in the pattern are also returned as part of the resulting
list.  If maxsplit is nonzero, at most maxsplit splits occur,
and the remainder of the string is returned as the final element
of the list.
File:      /usr/local/lib/python3.5/re.py
Type:      function

In [58]: re.split(r'[;,|\t]+',s)
Out[58]: ['ab', 'cd', 'efg', 'hi', 'jkl', 'mn', 'opq', 'rst', 'uvw', 'xyz']

問題二:如何判斷字符串a是否以字符串b開頭或結尾蛤奥?

問題內容:
某文件系統(tǒng)目錄下有一些列文件:
qudsn.rc
cadbh.py
ajcn.java
njasd.sh
wneacm.cpp
......
編寫程序給其中所有 .sh文件和 .py文件加上用戶可執(zhí)行權限。

解決方案:
使用字符串的str.startswitch()和str.endswith()方法
注意:多個匹配時參數(shù)使用元組

In [1]: ls
a.py  b.sh  c.java  d.h  e.cpp  f.c

In [2]: import  os,stat 

In [3]: os.listdir('.') 
Out[3]: ['a.py', 'b.sh', 'c.java', 'd.h', 'e.cpp', 'f.c']

In [4]: s = 'g.sh' 

In [5]: s.endswith('.sh') 
Out[5]: True

In [6]: s.endswith('.py') 
Out[6]: False

當傳入為元組的時候僚稿,只要有一個成立,就會返回True
In [7]: s.endswith(('.sh','.py')) 
Out[7]: True
還有就是蟀伸,傳入的參數(shù)只能為元組蚀同,不能為列表
In [8]: s.endswith(['.sh','.py']) 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-2b9d4c4a32cd> in <module>()
----> 1 s.endswith(['.sh','.py'])

TypeError: endswith first arg must be str or a tuple of str, not list

下面我們給指定文件授予權限:

In [9]: [ name for name in os.listdir('.') if  name.endswith(('.sh','.py'))]
Out[9]: ['a.py', 'b.sh']

查看當前文件狀態(tài),其中的st_mode為狀態(tài)碼
In [11]: os.stat('a.py')
Out[11]: os.stat_result(st_mode=33188, st_ino=3678001, st_dev=2051, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1491533824, st_mtime=1491533824, st_ctime=1491533824)

In [12]: os.stat('a.py').st_mode
Out[12]: 33188

將狀態(tài)碼轉為八進制啊掏,后三位就是我們平時看的777.
In [13]: oct(os.stat('a.py').st_mode)
Out[13]: '0o100644'

我們將狀態(tài)碼和stat.S_IXUSR 進行并集操作蠢络,X 代表執(zhí)行,USR代表用戶
In [17]: os.chmod('a.py',os.stat('a.py').st_mode | stat.S_IXUSR) 

In [18]: os.stat('a.py').st_mode
Out[18]: 33252
文件被賦予執(zhí)行權限
In [19]: ls -l 
total 0
-rwxr--r-- 1 root root 0 Apr  7 10:57 a.py*
-rw-r--r-- 1 root root 0 Apr  7 10:57 b.sh
-rw-r--r-- 1 root root 0 Apr  7 10:57 c.java
-rw-r--r-- 1 root root 0 Apr  7 10:57 d.h
-rw-r--r-- 1 root root 0 Apr  7 10:57 e.cpp
-rw-r--r-- 1 root root 0 Apr  7 10:57 f.c

問題三:如何調整字符串中文本的格式迟蜜?

問題內容:
某log文件刹孔,其中的日期格式為
......
t=2017-04-07T15:47:00+0800 lvl=eror msg="Metrics: GraphitePublisher: Failed to connect to [dial tcp [::1]:2003: getsockopt: connection refused]!"
t=2017-04-07T15:47:10+0800 lvl=eror msg="Metrics: GraphitePublisher: Failed to connect to [dial tcp [::1]:2003: getsockopt: connection refused]!"
t=2017-04-07T15:47:20+0800 lvl=eror msg="Metrics: GraphitePublisher: Failed to connect to [dial tcp [::1]:2003: getsockopt: connection refused]!"
t=2017-04-07T15:47:30+0800 lvl=eror msg="Metrics: GraphitePublisher: Failed to connect to [dial tcp [::1]:2003: getsockopt: connection refused]!"
......

我們想把其中的日期格式改為美國日期格式'mm/dd/yyyy','2017-04-07'=>'04/07/2017'娜睛,該如何處理髓霞?

解決方案:
使用正則表達式re.sub()方法做字符串替換惹悄,利用正則表達式的捕獲組邑闺,捕獲每個部分內容,在替換字符串中調整各個捕獲組的順序弯院。

In [8]: log = open('gdash.log').read()

In [9]: import re 

In [10]: re.sub?
Signature: re.sub(pattern, repl, string, count=0, flags=0)
Docstring:
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl.  repl can be either a string or a callable;
if a string, backslash escapes in it are processed.  If it is
a callable, it's passed the match object and must return
a replacement string to be used.
File:      /usr/local/lib/python3.5/re.py
Type:      function

In [12]: re.sub('(\d{4})-(\d{2})-(\d{2})',r'\2/\3/\1',log)

其中的 \1 代表第一個組障斋,我們還可以給組進行設置組名

In [14]: re.sub('(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',r'\g<month>/\g<day>/\g<year>',log)

問題五:如何對字符串進行左纵潦,右,居中對齊垃环?

某個字典存儲了一系列屬性值:

{
  "lodDISt":1000.0,
  "ejfmkd":0.01
  "ajdmea":30.0
  "jrfenim":322
}

在程序中邀层,我們想以下面的工整的格式將其輸出,如何處理遂庄?

lodDISt :1000.0,
ejfmkd  :0.01
ajdmea  :30.0
jrfenim :322

方法一:使用字符串的str.ljust()寥院,str.rjust(),str.center()進行左涛目,右只磷,居中對齊。
方法二:使用format()方法泌绣,傳遞類似'<20'钮追,'>20','^20'參數(shù)完成同樣任務阿迈。

In [1]: s = 'abc' 
查看方法的詳解
In [2]: s.ljust?
Docstring:
S.ljust(width[, fillchar]) -> str

Return S left-justified in a Unicode string of length width. Padding is
done using the specified fill character (default is a space).
Type:      builtin_function_or_method

In [3]: s.ljust(20)
Out[3]: 'abc                 '

傳入的第二個參數(shù)為填充值
In [4]: s.ljust(20,'=')
Out[4]: 'abc================='

In [5]: s.rjust(20)
Out[5]: '                 abc'

In [6]: len(s.rjust(20))
Out[6]: 20

In [7]: s.center(20)
Out[7]: '        abc         '

使用format()方法

In [8]: format?
Signature: format(value, format_spec='', /)
Docstring:
Return value.__format__(format_spec)

format_spec defaults to the empty string
Type:      builtin_function_or_method
左對齊:
In [9]: format(s,'<20')
Out[9]: 'abc                 '
右對齊:
In [10]: format(s,'>20')
Out[10]: '                 abc'
居中:
In [11]: format(s,'^20') 
Out[11]: '        abc         '

我們看下問題內容:

In [14]: d
Out[14]: {'ajdmea': 30.0, 'ejfmkd': 0.01, 'jrfenim': 322, 'lodDISt': 1000.0}

In [15]: d.keys()
Out[15]: dict_keys(['lodDISt', 'jrfenim', 'ajdmea', 'ejfmkd'])
獲得鍵長的列表
In [16]: map(len,d.keys())
Out[16]: <map at 0x7fe9eb59ea20>

In [17]: list(map(len,d.keys()))
Out[17]: [7, 7, 6, 6]

In [18]: max(map(len,d.keys()))
Out[18]: 7

In [19]: w = max(map(len,d.keys())) 

In [20]: for k in d:
    ...:     print(k.ljust(w),':',d[k])
    ...:     
lodDISt : 1000.0
jrfenim : 322
ajdmea  : 30.0
ejfmkd  : 0.01

問題六:如何去掉字符串中不需要的字符

問題內容:
1元媚,過濾掉用戶輸入中的前后多余的空白字符
2,過濾某windows下編輯文本中的'\r'
3,去掉文本中的unicode組合符號(音調)

解決方案:
方法一:字符串strip()刊棕,lstrip()炭晒,rstrip()方法去掉字符串兩端字符
方法二:刪除單個固定位置的字符,可以使用切片 + 拼接的方式
方法三:字符串的replace()方法或正則表達式re.sub()刪除任一位置字符
方法四:字符串translate()方法甥角,可以同事刪除多種不同字符

去除前后的空白

In [21]: s = '   abc   123   '

In [22]: s.strip?
Docstring:
S.strip([chars]) -> str

Return a copy of the string S with leading and trailing
whitespace removed.
If chars is given and not None, remove characters in chars instead.
Type:      builtin_function_or_method
當為指定字符時网严,默認去除空白字符
In [23]: s.strip()
Out[23]: 'abc   123'

In [24]: s.lstrip()
Out[24]: 'abc   123   '

In [25]: s.rstrip()
Out[25]: '   abc   123'

In [26]: s = '---abc+++'
當指定去除字符的時候
In [27]: s.strip('-+')
Out[27]: 'abc'

In [28]: s.lstrip('-')
Out[28]: 'abc+++'

In [29]: s.rstrip('+')
Out[29]: '---abc'

刪除固定位置的字符:

In [30]: s = 'abc:123' 
去除字符串中的 : 
In [31]: s[:3] + s[4:] 
Out[31]: 'abc123'

使用替換方法:

In [32]: s = '\tabc\t123\t' 

In [33]: s.replace('\t','')
Out[33]: 'abc123'

但是replace()方法只能替換單一的字符,當有多種字符的時候嗤无,可以使用正則表達式的sub()方法震束。

In [34]: s = '\tabc\t123\txyz\ropq\r' 

In [35]: import  re

In [36]: re.sub('[\t\r]','',s) 
Out[36]: 'abc123xyzopq'

使用tanslate()方法

我們看下translate方法的選項,第一個是映射表当犯,第二個是要刪除的字符
In [37]: str.translate?
Docstring:
S.translate(table) -> str

Return a copy of the string S in which each character has been mapped
through the given translation table. The table must implement
lookup/indexing via __getitem__, for instance a dictionary or list,
mapping Unicode ordinals to Unicode ordinals, strings, or None. If
this operation raises LookupError, the character is left untouched.
Characters mapped to None are deleted.
Type:      method_descriptor

In [38]: s = 'abc123456xyz' 

In [42]: tal = str.maketrans('abcxyz','xyzabc')

In [43]: s.translate(tal)
Out[43]: 'xyz123456abc'

注意:在python3中垢村,這兩種方法被包含到str類的方法中,就是說不用import string就可以直接用兩種方法嚎卫。

使用translate()方法刪除指定字符

In [54]: s = 'abc\refg\n234\t' 
首先設置映射表
In [55]: map = str.maketrans('','','\r\t\n')

In [56]: s.translate(map)
Out[56]: 'abcefg234'

使用translate()方法嘉栓,看截圖

Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拓诸,隨后出現(xiàn)的幾起案子侵佃,更是在濱河造成了極大的恐慌,老刑警劉巖奠支,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趣钱,死亡現(xiàn)場離奇詭異,居然都是意外死亡胚宦,警方通過查閱死者的電腦和手機首有,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枢劝,“玉大人井联,你說我怎么就攤上這事∧裕” “怎么了烙常?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鹤盒。 經常有香客問我蚕脏,道長,這世上最難降的妖魔是什么侦锯? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任驼鞭,我火速辦了婚禮,結果婚禮上尺碰,老公的妹妹穿的比我還像新娘挣棕。我一直安慰自己译隘,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布洛心。 她就那樣靜靜地躺著固耘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪词身。 梳的紋絲不亂的頭發(fā)上厅目,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音法严,去河邊找鬼损敷。 笑死,一個胖子當著我的面吹牛渐夸,可吹牛的內容都是我干的。 我是一名探鬼主播渔欢,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼墓塌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奥额?” 一聲冷哼從身側響起苫幢,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垫挨,沒想到半個月后韩肝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡九榔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年哀峻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哲泊。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡剩蟀,死狀恐怖,靈堂內的尸體忽然破棺而出切威,到底是詐尸還是另有隱情育特,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布先朦,位于F島的核電站缰冤,受9級特大地震影響,放射性物質發(fā)生泄漏喳魏。R本人自食惡果不足惜棉浸,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刺彩。 院中可真熱鬧涮拗,春花似錦乾戏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呐能。三九已至摆出,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偎漫,已是汗流浹背象踊。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工袖外, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留泌射,地道東北人魄幕。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓留储,卻偏偏與公主長得像阴颖,于是被迫代替她去往敵國和親量愧。 傳聞我的和親對象是個殘疾皇子煞烫,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容