python_cookbook学习

字符串和文本处理

针对任意多的分隔符拆分字符串

问题一:我们需要将字符串拆分为不同的字段,但是分隔符(以及分隔符之间的空格)

解决方法:
字符串的split()只能处理简单情况,这里我们使用re模块

import re
line = "sadb,dsada  , dsaa,hehe;   haha  "
result = re.split(r"[;,\s]\s*",line)  
#  \s 代表匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
print(result)
>> ['sadb', 'dsada', '', 'dsaa', 'hehe', 'haha', '']

要想处理最后面的空字符使用下面方式:

line = line.strip()  # 去掉字符串前后两边的空,换行字符 还有 lstrip方法和 rstrip方法
result = re.split(r"[;,\s]\s*",line)
print(result)
>> ['sadb', 'dsada', '', 'dsaa', 'hehe', 'haha']

注意:
这里正则表达式使用的是 [] 而 非 () ,如果使用()也就是正则表达式的捕获组
那么匹配的文本也会出现在结果里面。[] 是代表[]里面的满足其一就可以匹配。

line = "sadb,dsada  , dsaa,hehe;   haha  "
line = line.strip()
result = re.split(r"[;,\s]\s*",line)
print(result)
>> ['sadb', ',', 'dsada', ' ', '', ',', 'dsaa', ',', 'hehe', ';', 'haha']

如果想要使用()并且不带有捕获组的功能,请使用(?:pattern)

line = "sadb,dsada  , dsaa,hehe;   haha  "
line = line.strip()
result = re.split(r"(;|,|\s)\s*",line)
print(result)
result1 = re.split(r"(?:,|;|\s)\s*",line)
print(result1)
>> ['sadb', 'dsada', '', 'dsaa', 'hehe', 'haha']

如果你想要只是去掉多余的空格你也可以这样做

line = "asdf  fjdk; afed, fjek,asdf,   foo"
res = re.split(r"(;|,|\s)\s*",line)
values = res[::2]
print(values,1)
>> ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo'] 1
delimiters = res[1::2] + [""]  # 下面的zip函数转字典的时候以小的为基准
# 大的列表,多余的会被丢弃,所以添加一个多余的元素
print(delimiters,2)
>> [' ', ';', ',', ',', ',', ''] 2
print([v+d for v,d in zip(values,delimiters)],3)
>> ['asdf ', 'fjdk;', 'afed,', 'fjek,', 'asdf,', 'foo'] 3
print(dict(zip(values,delimiters)),4)
>> {'asdf': ' ', 'fjdk': ';', 'afed': ',', 'fjek': ',', 'foo': ''} 4
res2 = "".join(v+d for v,d in zip(values,delimiters))
print(res2)
>> "asdf fjdk;afed,fjek,asdf,foo"

如果是中文的字符串,去掉空格可以使用re.sub()方法,但引文不行,因为英文以空格分隔

str = "哈喽 你是? 哈 哈"
res = re.sub(r"\s*","",str)
print(res)
>> "哈喽你是?哈哈"

在字符串的开头或结尾处做文本匹配

一种简单的方法是使用str.startswith()或者str.endswith()方法就可以了

filename = "test.txt"
res = filename.endswith(".txt")
print(res)
>> True
res = filename.startswith("haha")
print(res)
>> False
url = "http://www.baidu.com"
res = url.endswith(".cn")
print(res)
>> False

如果需要同时对多个选项做检查,只需要把参数由字符串改为元组即可。
注:不能使用列表或者集合,必须是元组

import os
# 假设当前文件夹有 目录 test ,文件 test.py , test.js, test.txt
filenames = os.listdir(".")  # .代表当前文件夹  返回结果是列表  
print(filenames)
>> ["test", "test.py", "test.js", "test.txt"]
name = [name for name in filenames if name.endswith((".txt",".py"))]
print(name)
>>["test.py", "test.txt"]
# python 内建方法 any 和 all
res = any(name.endswith(".py") for name in filenames)
print(res)
>> True
res = all(name.endswith(".py") for name in filenames)
print(res)
>> False

又比如,从传入的参数获取内容,如果参数是网址,则从网址读取内容,
如果是文件名,使用文件处理。

from urllib.request import urlopen
def read_body(arg1):
    if arg1.startswith(("http:","https:","ftp:")):
        return urlopen(arg1).read()
    else:
        with open(arg1,"r") as file:
            res = file.read()
        return res

当然使用字符串的切片也可以解决

file_name = "test.txt"
print(file_name[-1:-4:-1] == "txt")
>> True

也可以使用正则表达式进行判断

import re
url = "http://www.baidu.com"
res = re.match(r"^(http|https|ftp).*$",url)
print(res.group(0))
>> http://www.baidu.com
print(res.group(1))
>> http

注:正则re的通配符和shell下的通配符是略有不同的

正则的?,代表前一个字符可有可无
shell的? 代表当前位置的字符是什么我不关系
正则的*  代表前一个字符出现多少次都可以 , 一般和  .* 搭配
shell 的 *  代表当前位置到后面位置是什么字符我不关心
比如: shell 的  da*  以da开头就行,后面的不管
  da*ad  以da 开头 ad结尾就行,中间是什么不管

普通文本的匹配使用str.find() 和 str.startswith() 和 str.endswith()
更复杂的匹配就使用正则表达式re
如果一个正则表达式规则可能会多次使用,你可以使用re的compile方法

# 不使用compile方法
import re
text = "2018/06/12"
if re.match(r"\d+/\d+/\d+",text):
    print("yes")
else:
    print("no")
# 使用compile方法
rule = re.compile(r"\d+/\d+/\d+")
if rule.match(text):
    print("yes")
else:
    print("no")

使用正则表达式对文本查找和替换的时候不区分大小写

可以对正则加上re.IGNORECASE标记

import re
text = "HAHA, Hello world"
res = re.findall("HAHA", text, re.IGNORECASE)
print(res)
>> ["HAHA"]

使用正则替换的特殊情况

根据原字符的大小写决定替换后的字符的大小写

import re
text = "HAHA, Haha haha  haHa"

def matchcase(word):
    def replace(m):
        text = m.group() # 这个 m是 re.search().group() 取匹配到的结果
        if text.isupper():
            return word.upper()
        elif text.islower():
            return word.lower()
        elif text[0].isupper():
            return word.capitalize()
        else:
            return word
    return replace

res = re.sub("haha", matchcase("hello"), text, flags=re.IGNORECASE)
print(res)
>> HELLO, Hello hello  hello
text = "hha"
print(re.search("h",text).group())
>> h

正则表达式在*号后面加?修饰符可以让贪婪模式变为非贪婪模式。

编写可以匹配换行符的正则表达式

使用管道符为 . 添加换行符匹配

import re
str = """/* hah
       */"""
res = re.findall(r"/\*(.|\n)*\*/",str)
print(res)
>>[' ']
res = re.findall(r"/\*(?:.|\n)*\*/",str)
print(res)
>>['/* hah\n       */']

处理字符串中的特殊字符

如果想要处理字符串的开始和结尾处的空格,可以直接使用strip方法.
如果想要处理开始和结尾处的非空格字符,在strip()方法里面添加要去除的字符,比如strip("-")
如果想要处理字符串中间的内容,就要使用字符串的replace方法或者正则表达式的sub方法.

s = "hello      word"
s.replace(" ","")
>>>helloword
import re
re.sub("\s+"," ",s)
>>>hello world

不过这些去除特殊字符操作,通常同迭代器相结合起来

with open(filename,"r") as f:
    lines = (line.strip() for line in f)   # 注意这里是生成器,不是列表生成式
    for line in lines:
        pass

当我们想清楚整个范围内的字符时,或者去掉音符标志.可以使用str.translate()方法

s = "python\fis\tawesome\r\n"
remap = {
    ord("\t"):" ",
    ord("\t"):" ",
    ord("\t"):None    #delete
}
a = s.translate(remap)
a
>>> python is awesome\n

字符串的常用操作:
str.upper()
str.lower()
str.find()
str.replace()
str.translate()
re.search()
re.match()
re.sub()
re.findall()

字符串的对齐操作:
使用字符串的just方法

text = "hello world"
text.ljust(20)
>>>"hello world     "
text.rjust(20)
>>>"    hello world"
text.center(20)
>>>"   hello world  "
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容