搜索精确的字符串,将其匹配。如果没有匹配的条目,则添加参数;如果部分匹配,则修改python文件

时间:2019-01-17 04:22:32

标签: python python-3.x

我有一个文件/etc/sysctl.conf,想要搜索以下2个字符串。如果找不到这样的字符串,我们需要在文件后追加相同的字符串。如果找不到完全匹配的内容,我们需要对其进行更正或删除行并添加。如果完全匹配未对文件执行任何操作。 我无法替换文件。请指导。

搜索字符串:

net.ipv4.ipfrag_low_thresh = 15728640 net.ipv4.ipfrag_high_thresh = 16777216

我的代码

          #/usr/bin/python
import os,datetime,shutil,re

num1 = 'net.ipv4.ipfrag_low_thresh = 15728640'
num = "net.ipv4.ipfrag_high_thresh = 16777216"

''' This Programme checks ipfrag value in /etc/sysctl.conf .
It also checks parameter in /proc/net/ip4

'''

date = datetime.datetime.today().strftime('%Y-%m-%d')
find_low_thresh=re.compile(r'net.ipv4.ipfrag_low_thresh\s*=\s*15728640')
find_high_thresh=re.compile(r'net.ipv4.ipfrag_high_thresh\s*=\s*16777216')
find_low_thresh1 = re.compile(r'net.ipv4.ipfrag_low_thresh*')
find_high_thresh1 = re.compile(r'net.ipv4.ipfrag_high_thresh*')
low_count=0

for i, line in enumerate(open("/etc/sysctl.conf", "r")):
    for match in re.finditer(find_low_thresh1,line):
        print(match.group())
        S3=match.group()
        print(S3)
        low_count+=1


if low_count == 0:
    print("Count is Zero and no match found")
        with open("/etc/sysctl.conf", "a") as myfile:
        myfile.write( "net.ipv4.ipfrag_low_thresh = 15728640\n")


elif low_count == 1:
    print("Counter is one")
    with open("/etc/sysctl.conf", "a") as myfile:
        myfile.write(re.sub("net.ipv4.ipfrag_low_thresh","net.ipv4.ipfrag_low_thresh = 15728640\n"))
else:
    print("Do Nothing")

#####################################################

if os.path.isfile("/etc/sysctl.conf." + date):
    print("File already exists")
else:
    print("It Does not exists,Copying file")
    shutil.copy("/etc/sysctl.conf", "/etc/sysctl.conf."+date)

if os.path.isfile("/etc/sysctl.conf." + date):
    S2="File already exists"
    print(S2)

else:
    print("File copiped")

2 个答案:

答案 0 :(得分:1)

这是使用python数据类型而不是仅使用字符串正则表达式的另一种方法(弄乱正则表达式并破坏文件结构太容易了。)

使用伪造的示例文件:

# hash comment
 ; colon comment

one = 1
net.ipv4.ipfrag_low_thresh = 1234
another = ok

代码:

#!/usr/bin/env python

setting_map = {
    'net.ipv4.ipfrag_low_thresh': 15728640,
    'net.ipv4.ipfrag_high_thresh': 16777216,
}
found = {setting: False for setting in setting_map}
to_write = []

def good_setting(setting):
    return '{} = {}'.format(setting, setting_map[setting])

with open('sysctl.conf') as f:
    for line in f:
        line = line.rstrip()  # remove newlines

        try:
            setting = line.split('=')[0].strip()  # remove spaces if present
            value = int(line.split('=')[-1].strip())
        except Exception as e:
            # you probably don't want to print, but i put it here for demonstration
            print('could not parse line "{}"; exception: {}'.format(line, repr(e)))
            # keep it as-is
            to_write.append(line)
            continue

        if setting in setting_map:
            found[setting] = True
            if value != setting_map[setting]:
                print('FOUND "{}" with value "{}"; overwriting with "{}"'.format(
                    setting, value, setting_map[setting]
                ))
                to_write.append(good_setting(setting))
                continue

        to_write.append(line)

# opening as 'w' will wipe the file, but we're re-writing every line
# or you can write to a different file if you'd like
with open('sysctl.conf', 'w') as f:
    f.write('\n'.join(to_write))
    f.write('\n')
    for setting in setting_map:
        if not found[setting]:
            print('ADDING "{}"'.format(good_setting(setting)))
            f.write('{}\n'.format(good_setting(setting)))

输出:

could not parse line "# hash comment"; exception: ValueError("invalid literal for int() with base 10: '# hash comment'")
could not parse line " ; colon comment"; exception: ValueError("invalid literal for int() with base 10: '; colon comment'")
could not parse line ""; exception: ValueError("invalid literal for int() with base 10: ''")
FOUND "net.ipv4.ipfrag_low_thresh" with value "1234"; overwriting with "15728640"
could not parse line "another = ok"; exception: ValueError("invalid literal for int() with base 10: 'ok'")
ADDING "net.ipv4.ipfrag_high_thresh = 16777216"

之后的文件:

# hash comment
 ; colon comment

one = 1
net.ipv4.ipfrag_low_thresh = 15728640
another = ok
net.ipv4.ipfrag_high_thresh = 16777216

答案 1 :(得分:0)

re.sub()具有3个参数,但这不是真正的问题。您实际上不会用简单的文件写入来替换要尝试替换的文本,而无需先使用seek()函数来查找要写入的偏移量。但是,这对您来说是个问题,因为替换字符串比原始字符串长,并且您最终可能会覆盖不想要的数据。另一个问题是您选择打开文件进行追加,在某些系统中,该文件只会追加到文件末尾,我确定这不是您的意图。

您真正需要做的就是打开文件并将数据复制到变量中。 然后,尝试找到该字符串并替换它。最后,将整个内容写回到文件中。

def write_over():
    file_name = '/etc/sysctl.conf'
    new_string = 'net.ipv4.ipfrag_low_thresh = 15728640'

    fh = open(file_name, 'r+')
    data = fh.read()

    result = re.search(r'net\.ipv4\.ipfrag_low_thresh\s?=?\s?[0-9]*', data) # check this regex, it may not be exactly what you need
    if result:
        if result.group(0) == new_string:  # if the string is exact match, do nothing
            fh.close()
            return
        data = data.replace(result.group(0), new_string + '\n') # else replace with new string
        fh.truncate(0) # this will clear the contents of the file
        fh.seek(0)
        fh.write(data) # write the new data in its entirety to the file
        fh.close()
    else:
        fh.write('\n' + new_string) # if the line was not in the file at all
        fh.close()