loop - for else python
coincidencia de patrĂ³n y reemplazar la cadena con if else loop (3)
Tengo un archivo que contiene varias líneas que comienzan con "1ECLI H --- 12.345 .....". Quiero eliminar un espacio entre I y H y agregar R / S / T sobre la iteración del patrón H. por ej. H810 si se repite en tres líneas consecutivas, se debe agregar con una letra R, S (segunda iteración), T (tercera iteración). por lo que sería H810R. Cualquier ayuda será apreciada.
el texto se ve a continuación
1ECLI H813 98 7.529 8.326 9.267
1ECLI H813 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814 101 7.607 8.617 9.289
1ECLI H814 102 7.633 8.489 9.156
1ECLI H814 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
sobre chage
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814s 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
Gracias.
El siguiente código asume que las lines
es una lista de cadenas que representan una línea en su archivo.
with open(''filename'') as f:
lines = f.readlines()
from collections import defaultdict
cntd = defaultdict(lambda: 0)
suffix = [''R'', ''S'', ''T'']
newlines = []
for line in lines:
try:
kwd = line.split()[1]
except IndexError:
newlines.append(line)
continue
if kwd[0] == ''H'' and kwd[-1].isdigit():
sfx = suffix[cntd[kwd]]
idx = line.index(kwd)
nl = line[:idx -1] + kwd + sfx + line[idx + len(kwd):]
# nl = line[:idx + len(kwd)] + sfx + line[idx + len(kwd):] # adjust formatting to your taste
newlines.append(nl)
cntd[kwd] += 1
else:
newlines.append(line)
with open(''filename'', ''w'') as f:
f.writelines(newlines)
Incluso debajo de uno puede dar el resultado deseado, si su archivo de entrada real es el mismo que el que ha publicado.
awk ''BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}1'' infile
Explicación
split("R,S,T",a,/,/)
- dividir la secuencia"R,S,T"
por la coma separadora, y guardar en la matriza
, por lo que se conviertea[1] = R, a[2] = S, a[3] = T
f=$2~/^H[0-9]+$/
-f
es variable, valide la expresión regular$2 ~ /^H[0-9]+$/
, que devuelve el estado booleano. si devuelvetrue
, la variablef
será verdadera, de lo contrariofalse
$2 = $2 a[++c]
si el anterior es verdadero, luego modifique el segundo campo, entonces el segundo campo tendrá el valor existente más el arsenala
valor, correspondiente al índice (c
),++c
es una variable de preincremento!f{c=0}
si la variablef
es falsa, reinicie la variablec
, no consecutivamente.1
al final realiza la operación predeterminada que es imprimir actual / grabar / fila,print $0
. Para saber cómo funciona awk, pruebaawk ''1'' infile
, que imprimirá todos los registros / líneas, mientras queawk ''0'' infile
imprime nada. Cualquier número que no sea cero es verdadero , lo que desencadena el comportamiento predeterminado.
Resultados de la prueba:
$ cat infile
1ECLI H813 98 7.529 8.326 9.267
1ECLI H813 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814 101 7.607 8.617 9.289
1ECLI H814 102 7.633 8.489 9.156
1ECLI H814 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
$ awk ''BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}1'' infile
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814S 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
Si desea formatear mejor como una tab
o algún otro carácter como separador de campo, puede usar debajo de uno, modificar la variable OFS
$ awk -v OFS="/t" ''BEGIN{split("R,S,T",a,/,/)}f=$2~/^H[0-9]+$/{$2 = $2 a[++c]}!f{c=0}{$1=$1}1'' infile
1ECLI H813R 98 7.529 8.326 9.267
1ECLI H813S 99 7.427 8.470 9.251
1ECLI C814 100 7.621 8.513 9.263
1ECLI H814R 101 7.607 8.617 9.289
1ECLI H814S 102 7.633 8.489 9.156
1ECLI H814T 103 7.721 8.509 9.305
1ECLI C74 104 8.164 8.733 10.740
1ECLI H74R 105 8.247 8.690 10.799
Si su archivo de entrada es el mismo que el ejemplo mostrado, ¿podría intentar seguir awk
y decirme si esto lo ayuda?
awk ''
BEGIN{
val[1]="R";
val[2]="S";
val[3]="T"
}
$2 !~ /^H[0-9]+/ || i==3{
i=""
}
$2 ~ /^H[0-9]+$/ && /^1ECLI/{
$2=$2val[++i]
}
1
'' Input_file > temp_file && mv temp_file Input_file
Agregando la explicación también para la respuesta también de la siguiente manera.
awk ''
BEGIN{ ##Starting BEGIN section of awk here.
val[1]="R"; ##creating an array named val whose index is 1 and value is string R.
val[2]="S"; ##creating array val 2nd element here whose value is S.
val[3]="T" ##creating array val 3rd element here whose value is T.
}
$2 !~ /^H[0-9]+/ || i==3{ ##Checking condition if 2nd field does not start from H and digits after that OR variable i value is equal to 3.
i="" ##Then nullifying the value of variable i here.
}
$2 ~ /^H[0-9]+$/ && /^1ECLI/{ ##Checking here if 2nd field value is starts from H till all digits till end AND line starts from 1ECLI string then do following.
$2=$2val[++i] ##re-creating value of 2nd field by adding value of array val whose index is increasing value of variable i.
}
1 ##Mentioning 1 here, which means it will print the current line.
'' Input_file > temp_file && mv temp_file Input_file ##Mentioning Input_file name here.