web-dev-qa-db-fra.com

Comment faire comme texte remplacer par python?

Je souhaite activer tous les référentiels apt dans ce fichier

cat /etc/apt/sources.list
## Note, this file is written by cloud-init on first boot of an instance                                                                                                            
## modifications made here will not survive a re-bundle.                                                                                                                            
## if you wish to make changes you can:                                                                                                                                             
## a.) add 'apt_preserve_sources_list: true' to /etc/cloud/cloud.cfg                                                                                                                
##     or do the same in user-data
## b.) add sources in /etc/apt/sources.list.d                                                                                                                                       
#                                                                                                                                                                                   

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to                                                                                                           
# newer versions of the distribution.                                                                                                                                               
deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick main                                                                                                                   
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick main                                                                                                               

## Major bug fix updates produced after the final release of the                                                                                                                    
## distribution.                                                                                                                                                                    
deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates main                                                                                                           
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates main                                                                                                       

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu                                                                                                         
## team. Also, please note that software in universe WILL NOT receive any                                                                                                           
## review or updates from the Ubuntu security team.                                                                                                                                 
deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick universe                                                                                                               
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick universe                                                                                                           
deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates universe
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in 
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
# deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick multiverse
# deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick multiverse
# deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
# deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-updates multiverse

## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
# deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-backports main restricted universe multiverse
# deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu/ maverick-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu maverick partner
# deb-src http://archive.canonical.com/ubuntu maverick partner

deb http://security.ubuntu.com/ubuntu maverick-security main
deb-src http://security.ubuntu.com/ubuntu maverick-security main
deb http://security.ubuntu.com/ubuntu maverick-security universe
deb-src http://security.ubuntu.com/ubuntu maverick-security universe
# deb http://security.ubuntu.com/ubuntu maverick-security multiverse
# deb-src http://security.ubuntu.com/ubuntu maverick-security multiverse

Avec sed, il s'agit d'un sed -i 's/^# deb/deb/' /etc/apt/sources.list simple. Quelle est la manière la plus élégante ("Pythonic") de le faire?

39
Maxim Veksler

massedit.py ( http://github.com/elmotec/massedit ) effectue l'échafaudage pour vous en ne laissant que la regex à écrire. Il est toujours en version bêta mais nous recherchons des retours.

python -m massedit -e "re.sub(r'^# deb', 'deb', line)" /etc/apt/sources.list

montrera les différences (avant/après) au format diff. 

Ajoutez l'option -w pour écrire les modifications dans le fichier d'origine:

python -m massedit -e "re.sub(r'^# deb', 'deb', line)" -w /etc/apt/sources.list

Alternativement, vous pouvez maintenant utiliser l'api: 

>>> import massedit
>>> filenames = ['/etc/apt/sources.list']
>>> massedit.edit_files(filenames, ["re.sub(r'^# deb', 'deb', line)"], dry_run=True)
18
elmotec

Vous pouvez faire ça comme ça:

with open("/etc/apt/sources.list", "r") as sources:
    lines = sources.readlines()
with open("/etc/apt/sources.list", "w") as sources:
    for line in lines:
        sources.write(re.sub(r'^# deb', 'deb', line))

L'instruction with garantit que le fichier est correctement fermé. La réouverture du fichier en mode "w" le vide avant de l'écrire. re.sub (pattern, replace, string) est l'équivalent de s/pattern/replace/in sed/Perl.

Édition: syntaxe fixe dans l'exemple

46
David Miller

C'est une approche tellement différente que je ne veux pas modifier mon autre réponse . Nested with puisque je n'utilise pas la version 3.1 (Où with A() as a, B() as b: fonctionne).

Peut-être un peu exagéré de changer sources.list, mais je tiens à le mettre pour les recherches futures.

#!/usr/bin/env python
from shutil   import move
from tempfile import NamedTemporaryFile

with NamedTemporaryFile(delete=False) as tmp_sources:
    with open("sources.list") as sources_file:
        for line in sources_file:
            if line.startswith("# deb"):
                tmp_sources.write(line[2:])
            else:
                tmp_sources.write(line)

move(tmp_sources.name, sources_file.name)

Cela devrait garantir qu'aucune autre personne ne lise le fichier dans des conditions de concurrence critique… .. Oh, et je préfère str.startswith (...) lorsque vous pouvez vous passer d'une expression rationnelle.

12
plundra

Si vous utilisez Python3, le module suivant vous aidera: https://github.com/mahmoudadel2/pysed

wget https://raw.githubusercontent.com/mahmoudadel2/pysed/master/pysed.py

Placez le fichier de module dans le chemin de vos modules Python3, puis:

import pysed
pysed.replace(<Old string>, <Replacement String>, <Text File>)
pysed.rmlinematch(<Unwanted string>, <Text File>)
pysed.rmlinenumber(<Unwanted Line Number>, <Text File>)
6
M. Adel

Essayez https://pypi.python.org/pypi/pysed

pysed -r '# deb' 'deb' /etc/apt/sources.list

3
dslackw

Si vous voulez vraiment utiliser une commande sed sans installer un nouveau module Python, vous pouvez simplement procéder comme suit: 

import subprocess
subprocess.call("sed command")
2
Brad Jasperson

Vous pourriez faire quelque chose comme:

p = re.compile("^\# *deb", re.MULTILINE)
text = open("sources.list", "r").read()
f = open("sources.list", "w")
f.write(p.sub("deb", text))
f.close()

Alternativement (à mon humble avis, cela est préférable du point de vue organisationnel), vous pouvez scinder votre sources.list en plusieurs éléments (une entrée/un référentiel) et les placer sous /etc/apt/sources.list.d/

2
barti_ddu

Pas sûr d'élégant, mais cela devrait au moins être assez lisible. Pour une liste de sources, il est bon de lire toutes les lignes avant de commencer. Pour quelque chose de plus grand, vous voudrez peut-être changer "en place" en boucle.

#!/usr/bin/env python
# Open file for reading and writing
with open("sources.list", "r+") as sources_file:
    # Read all the lines
    lines = sources_file.readlines()

    # Rewind and truncate
    sources_file.seek(0)
    sources_file.truncate()

    # Loop through the lines, adding them back to the file.
    for line in lines:
        if line.startswith("# deb"):
            sources_file.write(line[2:])
        else:
            sources_file.write(line)

EDIT: Utilisez l'instruction with- pour une meilleure gestion des fichiers. Aussi oublié de rembobiner avant de tronquer avant.

2
plundra

Je voulais pouvoir trouver et remplacer du texte, mais aussi inclure des groupes correspondants dans le contenu que j'insère. J'ai écrit ce court script pour le faire:

https://Gist.github.com/turtlemonvh/0743a1c63d1d27df3f17

L'élément clé de cela est quelque chose qui ressemble à ceci:

print(re.sub(pattern, template, text).rstrip("\n"))

Voici un exemple de la façon dont cela fonctionne:

# Find everything that looks like 'dog' or 'cat' followed by a space and a number
pattern = "((cat|dog) (\d+))"

# Replace with 'turtle' and the number. '3' because the number is the 3rd matched group.
# The double '\' is needed because you need to escape '\' when running this in a python Shell
template = "turtle \\3"

# The text to operate on
text = "cat 976 is my favorite"

Appeler la fonction ci-dessus avec ceci donne:

turtle 976 is my favorite
1
turtlemonvh

Voici un remplacement d'un module Python pour Perl -p:

# Provide compatibility with `Perl -p`

# Usage:
#
#     python -mloop_over_stdin_lines '<program>'

# In, `<program>`, use the variable `line` to read and change the current line.

# Example:
#
#         python -mloop_over_stdin_lines 'line = re.sub("pattern", "replacement", line)'

# From the perlrun documentation:
#
#        -p   causes Perl to assume the following loop around your
#             program, which makes it iterate over filename arguments
#             somewhat like sed:
# 
#               LINE:
#                 while (<>) {
#                     ...             # your program goes here
#                 } continue {
#                     print or die "-p destination: $!\n";
#                 }
# 
#             If a file named by an argument cannot be opened for some
#             reason, Perl warns you about it, and moves on to the next
#             file. Note that the lines are printed automatically. An
#             error occurring during printing is treated as fatal. To
#             suppress printing use the -n switch. A -p overrides a -n
#             switch.
# 
#             "BEGIN" and "END" blocks may be used to capture control
#             before or after the implicit loop, just as in awk.
# 

import re
import sys

for line in sys.stdin:
    exec(sys.argv[1], globals(), locals())
    try:
        print line,
    except:
        sys.exit('-p destination: $!\n')
1
Matt McClure

Python a un module regex (import re). pourquoi vous ne voulez pas l'utiliser comme en Perl. Il a toutes les fonctionnalités d'une regex Perl

0
Arunmu