Newsgroup: it.comp.os.linux.sys
Titolo: sed: sostituzione prima occorrenza dopo pattern

Ho il seguente spezzone di file.
dovrei sostituire la prima occorrenza di una determinata stringa "35 days", dopo un determinato pattern: "xxxx-DifferentialPool".
 
Non ho la minima idea di come si faccia. Mi sapete dare qualche dritta?
 
Storage {
   Name = xxxx-Storage
   Address = 172.17.0.1
   SDPort = 9103
   Password = "x"
   Device = xxxx-FileStorage
   Media Type = xxxx-File
   Maximum Concurrent Jobs = 5
}
 
Pool {
   Name = xxxx-FullPool
   Label Format = "${Year}${Month:p/2/0/r}${Day:p/2/0/r}_${Hour:p/2/0/r}${Minute:p/2/0/r}-xxxx-full"
   Pool Type = Backup
   Recycle = no
   AutoPrune = yes
   Volume Retention = 35 days
   Maximum Volume Jobs = 1
   Action On Purge = Truncate
   Next Pool = TapePool
}
 
Pool {
   Name = xxxx-DifferentialPool
   Label Format = "${Year}${Month:p/2/0/r}${Day:p/2/0/r}_${Hour:p/2/0/r}${Minute:p/2/0/r}-xxxx-differential"
   Pool Type = Backup
   Recycle = no
   AutoPrune = yes
   Volume Retention = 35 days
   Maximum Volume Jobs = 1
   Action On Purge = Truncate
}
 
Pool {
   Name = xxxx-IncrementalPool
   Label Format = "${Year}${Month:p/2/0/r}${Day:p/2/0/r}_${Hour:p/2/0/r}${Minute:p/2/0/r}-xxxx-incremental"
   Pool Type = Backup
   Recycle = no
   AutoPrune = yes
   Volume Retention = 35 days
   Maximum Volume Jobs = 1
   Action On Purge = Truncate
}

 days", dopo un determinato pattern: "xxxx-DifferentialPool".
 
 
non è elegantissimo, ma funziona:
 
#!/usr/bin/env python
import os
 
input_file = 'input.txt'
output_file = 'output.txt'
 
try:
    os.remove(output_file)
except:
    pass
 
j = open(output_file, 'a+')
 
with open(input_file) as f:
    DATA = f.read()
    if 'Label Format' in DATA and '-differential' in DATA:
        action = True
    else:
        action = None
    if 'Volume Retention' in DATA and action:
        DATA = DATA.replace('35', 'whathever')
    j.write(DATA)
 
 
-- 
Massimiliano Adamo

 
 
prima abbiamo scherzato. Adesso funziona veramente :) 
 
 
#!/usr/bin/python
import os
 
input_file = 'input.txt'
output_file = 'output.txt'
 
try:
    os.remove(output_file)
except OSError:
    pass
 
j = open(output_file, 'a+')
f = open(input_file).readlines()
 
for data in f:
    if 'Label Format' in data and '-differential' in data:
        action = True
    elif 'Label Format' in data and '-differential' not in data:
        action = None
    if 'Volume Retention' in data and action:
        data = data.replace('35', 'whathever')
    j.write(data)
 
 
 
-- 
Massimiliano Adamo

 prima abbiamo scherzato. Adesso funziona veramente :) 
 
Intanto grazie.
Il problema è che con uno script del genere mi si complica un po, in realtà i file da modificare sono circa 90. Avevo chiesto di sed perchè avrei potuto fare un brutale ciclo for tramite bash e rimpiazzare tutto in automatico.
 
Con python dovrei quantomeno leggere lo stdin, e scrivere su stdout.
Adesso gooooogolo per vedere come si fa.


L'ho provato e dovrebbe funzionare.
input_dir è la directory che contiene i file da modificare.
 
#!/usr/bin/python
import os
from glob import glob
import shutil
 
input_dir = '/home/maxadamo/in/'
output_dir = '/home/maxadamo/out/'
 
shutil.rmtree(output_dir, ignore_errors=True)
 
try:
    os.makedirs(output_dir)
except:
    print 'could not create output dir'
    os.sys.exit(1)
 
 
for input_file in glob(input_dir + '*'):
    f = open(input_file).readlines()
    output_file = os.path.join(output_dir, os.path.basename(input_file))
    j = open(output_file, 'w')


 L'ho provato e dovrebbe funzionare.
 
Ha funzionato. Grazie!


magari si poteva fare anche con sed e ci sono persone che lo preferiscono. 
Per quel che mi riguarda è più il casino che tutto il resto. 
 
 
-- 
Massimiliano Adamo

 Per quel che mi riguarda è più il casino che tutto il resto. 
 
Personalmente, con sed e awk non sono mai riuscito ad andare oltre ad una semplice sostituzione globale o un print della colonna numero X.
 
Su questa macchina non ho PHP altrimenti avrei scriptato qualcosina, fortunatamente mi sei venuto in soccorso.

 Per quel che mi riguarda è più il casino che tutto il resto.
 
Non so, mi dà l'idea che ci voglia uno stato per avere un algoritmo 
semplice. Inoltre con una breve ricerca non ho capito come matchare \n 
in un gruppo con gsed, avrei detto che saltava subito fuori e invece no.
 
Insomma mi sembra che il tuo script sia una soluzione molto più 
pratica, forse qualche awk-ista scenderà dal cielo con uno one-liner 
adatto.
 
Curiosità: perché nella flag usi None come alternativa a True piuttosto 
che False ?
 
 
-- 
Andrea
 

 che False ?
 
bella domanda. Diciamo che ho sempre usato "None", in maniera un po' 
ignorante, ma scopro adesso che avrebbe funzionato anche con: 
action = False
action = ''
action = 0
action = []
action = {}
 
 
eppure sono gemelli diversi: 
if None == False:
    print 'they are the same'
else:
    print 'they are not the same'
 
 
dovrei scavare un po' per capire la vera differenza... 
 
-- 
Massimiliano Adamo

 Non ho la minima idea di come si faccia. Mi sapete dare qualche dritta?
 
Sarebbe meglio usare perl o AWK ma in questo caso:
 
sed  -e '/Name = xxxx-DifferentialPool/,/^}/ {s/35 days/2 months/}'
 
 
PS Esponi il tuo problema, non la tua soluzione.
 
 
 

 sed  -e '/Name = xxxx-DifferentialPool/,/^}/ {s/35 days/2 months/}'
 
Noice. È un approccio che non conoscevo e lo metto subito nel 
"quadernetto delle cose shelle".
 
 
-- 
Andrea
 

 Sarebbe meglio usare perl o AWK 
 
bee doo, bee doo, bee doo, bee doo... rischio flame elevatissimo :) 
 
 
-- 
Massimiliano Adamo

 PS Esponi il tuo problema, non la tua soluzione.
 
Dici a me ? Io ho esposto il problema, non la soluzione:
"dovrei sostituire la prima occorrenza di una determinata stringa "35 days", dopo un determinato pattern: xxxx-DifferentialPool."
 
ho anche scritto: "Non ho la minima idea di come si faccia."
 
Come potrei aver esposto la soluzione se non so nemmeno come si fa ?


Intendeva dire: perché vuoi sostituire quella stringa "35 days"? Dove? Con cosa?
 
Invento a man salva, e dico: vuoi riconfigurare un affare di backup. Magari tu ci dici quale,
e qualcuno sa che quel file di configurazione è generato in automatico da uno strumento GUI e
basta andare in VMBackup > Edit > Settings > Profile > Backups > Default > Retention, e da lì
impostare "20" invece di "35", quindi selezionare File > Save.
 
E' quello che si chiama "XY Approach" o "XY Problem" :-)
 
Leonardo
-- 
 
A terrible beauty is born.
                                     - W. B. Yeats, Easter 1916

 impostare "20" invece di "35", quindi selezionare File > Save.
 
Sei completamente fuori strada.
 
Devo riconfigurare svariati file di backup che IO ho creato mesi fa tramite un MIO script che ho scritto A MANO senza gui o cose simili.
 
Non ho idea di cosa sia lo strumento di cui parli e men che meno ho un "VMbackup" dato che ne il server su cui gira bacula ne il server che sto backuppando sono VM 
 
Non ho alcuna gui installata o alcuno strumento di gestione, si tratta di un comunissimo file di testo.
 
A volte pensare che l'op abbia scritto il problema e non la soluzione evita, come si suol dire, di farla fuori dal vaso.

 Devo riconfigurare svariati file di backup che IO ho creato mesi fa tramite un MIO script
 
probabilmente, nessuno avrebbe potuto equivocare: ma il fatto è che non l'avevi scritto. Scusa
dunque per il qui pro quo.


 Con cosa? 
 
no, perdonami. Intendeva dire che il subject contiene la soluzione: SED. 
 
il 35 days sono fattacci suoi. No? 
 
Difatti (secondo lui) sarebbe meglio perl o AWK. 
Secondo me, sarebbe meglio ciò con cui hai dimestichezza e ti fa perdere 
meno tempo. Lo puoi fare con ruby, all'incirca, lo puoi fare con ciò che 
ti aggrada. 
 
-- 
Massimiliano Adamo

no, perdonami. Intendeva dire che il subject contiene la soluzione: SED. 
 
Sì, sì. Non mi sono capito :-D


 ti aggrada. 
 
Immaginavo anche io il problema fosse "sed".
Ma in realtà, non è la soluzione. Potrei aver mille-mila motivi per usare sed,
magari non ho alcun linguaggio di scripting, magari la luna è calante quindi non funziona awk, etc etc. 
Pertanto, la mia domanda, sarebbe stata comunque valida: con sed come si fa?
 
Poi ammetto che non avevo pensato a perl e men che meno a python (che nemmeno sapevo di avere). sed mi è parsa la cosa migliore, tant'è che si è trattato di un one-liner piuttosto semplice, non ne vedo quindi il problema.
 
P.S: avevo chiesto sed per un motivo: posso metterlo in pipe all'interno di un ciclo in bash. Con python no, tant'è che il codice proposto è stato rimaneggiato in seguito per poter leggere tutti i file di una directory.
 

Addì  sabato 7 maggio 2016 08:09 Andrea D'Amore scrisse:

man sed
info sed
 

 ti aggrada.
 
Per il resto, quando le cose si complicano usi un vero e proprio
linguaggio di programmazione, che, qui diventa valida la tua osser_
vazione, è lo strumento a cui sei abituato che può essere Perl, AWK,
Ruby, Python etc. etc.
Ad esempio per la soluzione dell'OP, sostituire solo la prima occor_
renza di una stringa, io avrei usato VIM: è facile scrivere una macro 
che fa questo, è facile usare VIM per processare automaticamente 
anche migliaia di file. Come si fa lo trovate sul WEB.
 
 
 

 rimaneggiato in seguito per poter leggere tutti i file di una directory.
 
Guarda che anche con uno script Python puoi strutturare il suo 
output e sfruttare il suo /exit-status/ affinché sia inseribile in uno
script bash.
La questione è più sottile, nel senso che una volta usato Python 
fai tutto in Python ;-)
 
 
 

 WEB.
 
 
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >