Python - ¿Liste problemas (listas múltiples?)
Pregunta
El siguiente es una parte de un script que estoy tratando de escribir.El script abre mi registro de IPTables, cada línea en el registro contiene los detalles en el siguiente ejemplo.
#example of a single line #Mar 9 14:57:51 machine kernel: [23780.638839] IPTABLES Denied UDP: IN=p21p1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00 SRC=10.100.1.4 DST=10.100.1.63 LEN=78 TOS=0x00 PREC=0x00 TTL=128 ID=10898 PROTO=UDP$ # Read file in a line at a time for line in iptables_log.readlines(): #find time based on 4 letters, 2 spaces, up to 2 numbers, 1 space, then standard 10:10:10 time format time = re.findall('(^\w{1,4}\s\s\d{1,2}\s\d\d:\d\d:\d\d)', line) #mac lookup mac = re.findall('MAC=(?:\w\w:\w\w:\w\w:\w\w\:\w\w:\w\w:\w\w:\w\w:\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)', line) #source port src = re.findall('SRC=(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})', line) #destination port dst = re.findall('DST=(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})', line) #protocol proto = re.findall('PROTO=(?:\w{3,4})', line) #sourceport sourceport = re.findall('SPT=(?:\w{1,5})', line) #destport destport = re.findall('DPT=(?:\w{1,5})', line) print time, mac, src, dst, proto, sourceport, destport print '======================================================'
Estoy tratando de hacer que el script imprima solo los elementos que quiero, pero cuando la salida por el script se ve así, lo que parece ser una lista.Quiero que se imprima sin el [] ''.Mirando en línea Parece que todas las variables (tiempo, MAC, SRC, etc.) son una lista de ellos mismos.No estoy seguro de cómo combinarlos.He visto referencia a unirme, pero no estoy seguro de cómo usarlo este ejemplo.¿Alguien puede ayudar por favor?
['Mar 9 14:57:51'] ['MAC=ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00'] ['SRC=10.100.1.4'] ['DST=10.100.1.63'] ['PROTO=UDP'] ['SPT=137'] ['DPT=137']
Solución
¿Por qué no simplemente desempaquetar sus listas?
>>> time = [0]
>>> [time] = time
>>> time
0
Otros consejos
re.findall devuelve una lista
def findall(pattern, string, flags=0):
"""Return a list of all non-overlapping matches in the string.
If one or more groups are present in the pattern, return a
list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result."""
return _compile(pattern, flags).findall(string)
Yo usaría reinsearch en su lugar.
>>> import re
>>> st = '''Mar 9 14:57:51 machine kernel: [23780.638839] IPTABLES Denied UDP: IN=p21p1 OUT= MAC=ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00 SRC=10.100.1.4 DST=10.100.1.63 LEN=78 TOS=0x00 PREC=0x00 TTL=128 ID=10898 PROTO=UDP$'''
>>> x = re.search('(^\w{1,4}\s\s\d{1,2}\s\d\d:\d\d:\d\d)',st)
>>> x.group(0)
'Mar 9 14:57:51'
(source= http://docs.python.org/library/re.html)
Usted podría simplemente hacer:
foo = re.findall(…)[0]
Si espera un solo resultado, para cualquier re.finall
re.findall devuelve una lista de coincidencias.En su caso, está recibiendo listas con un solo valor.Si ese es siempre el caso, la respuesta @ x539 obtendrá el primer elemento en la lista.
Sugiero usar una sola regulación de línea completa, con grupos nombrados, tales como:
>>> r = re.compile(r'^(?P<date>\w{1,4}\s\d{1,2}\s\d\d\:\d\d\:\d\d) (?P<hostname>\w+) kernel: (\[[0-9]+.[0-9]+\]) IN=(?P<ifacein>[a-z0-9]*) OUT=(?P<ifaceout>[a-z0-9]*) MAC=(?P<mac>[a-f0-9:]+) SRC=(?P<src>[\w.:]+) DST=(?P<dst>[\w:.]+) LEN=(?P<len>[0-9]+) TOS=0x(?P<tos>[0-9a-f]+) PREC=0x(?P<prec>[0-9a-f]+) TTL=(?P<ttl>[0-9]+) ID=(?P<id>[0-9]+) PROTO=(?P<proto>[A-Z]+) SPT=(?P<spt>[0-9]+) DPT=(?P<dpt>[0-9]+) LEN=(?P<len2>[0-9]+)')
>>> d = r.match(line).groupdict()
>>> d['dst']
'255.255.255.255'
>>> d['proto']
'UDP'
>>> d['dpt']
'17500'
También puede volver fácilmente en una sola cadena con los campos que desea:
>>> ' '.join([d[_] for _ in ("date", "mac", "src", "dst", "proto", "spt", "dpt")])
'Mar 12 13:06:10 ff:ff:ff:ff:ff:ff:00:18:8b:da:86:37:08:00 192.168.0.221 255.255.255.255 UDP 17500 17500'