Tengo un registro que devuelve miles de líneas de datos, quiero extraer algunos valores de eso.

En el registro solo hay una línea que contiene la referencia unquie unit, por lo que puedo buscar eso usando:

grep "unit=Central-C152" logfile.txt

Eso produce una línea de salida similar a la siguiente:

a3cd23e,85d58f5,53f534abef7e7,unit=Central-C152,locale=32325687-8595-9856-1236-12546975,11="School",1="Mr Green",2="Qual",3="SWE",8="report",5="channel",7="reset",6="velum"

El formato de la línea puede cambiar porque el orden de los valores no siempre estará en la misma posición.

Estoy tratando de averiguar cómo obtener el valor de 2 y 7 para separar las variables. Había pensado en cut en, o = pero como los valores no están en un orden establecido, no pude encontrar la mejor manera de hacerlo.

Estoy tratando de obtener:

var state=value of 2 without quotes var mode=value of 7 without quotes

¿Alguien puede aconsejar sobre la mejor manera de hacer esto?

Gracias

0
Tom 17 sep. 2018 a las 10:35

3 respuestas

La mejor respuesta

¿Podría intentar lo siguiente para crear valores de variable?

state=$(awk '/unit=Central-C152/ && match($0,/2=\"[^"]*/){print substr($0,RSTART+3,RLENGTH-3)}' Input_file)
mode=$(awk '/unit=Central-C152/ && match($0,/7=\"[^"]*/){print substr($0,RSTART+3,RLENGTH-3)}'  Input_file)

También podrías imprimirlas haciendo lo siguiente.

echo "$state"
echo "$mode"

Explicación : Agregando la explicación del comando también ahora.

awk '                                           ##Starting awk program here.
/unit=Central-C152/ && match($0,/2=\"[^"]*/){   ##Checking condition if a line has string (unit=Central-C152) and using match using REGEX to check from 2 to till "
  print substr($0,RSTART+3,RLENGTH-3)           ##Printing substring starting from RSTART+3 till RLENGTH-3 characters.
}
' Input_file                                    ##Mentioning Input_file name here.
1
RavinderSingh13 17 sep. 2018 a las 13:41

Suponiendo que ya tiene la línea en una variable como con:

line="$(grep 'unit=Central-C152' logfile.txt | head -1)"

Luego, simplemente puede usar las funciones de sustitución de parámetros integradas de bash:

f2=${line#*2=\"} ; f2=${f2%%\"*} ; echo ${f2}
f7=${line#*7=\"} ; f7=${f7%%\"*} ; echo ${f7}

El primer comando en cada línea elimina la primera parte de la línea hasta e incluyendo <field-number>=". El segundo comando luego elimina todo lo que está más allá (e incluye) la primera cita. El tercero, por supuesto, simplemente refleja el valor.

Cuando ejecuto esos comandos contra su línea de entrada, veo:

Qual
reset

Que es, por lo que puedo ver, lo que estabas buscando.

1
paxdiablo 17 sep. 2018 a las 08:33

Probablemente sea mejor hacer todo el procesamiento en Awk.

awk -F, '/unit=Central-C152/ {
    for(i=1;i<=NF;++i)
        if($i ~ /^[27]="/) {
            b[++k] = $i
            sub(/^[27]="/, "", b[k])
            sub(/"$/, "", b[k])
            gsub(/\\/, "", b[k])
        }
    print "state " b[1] ", mode " b[2]
    }' logfile.txt

Esto presupone que los campos siempre ocurren en el mismo orden (2 antes que 7). Tal vez necesite cambiar o deshabilitar gsub para eliminar las barras invertidas en los valores.

Si desea hacer más que imprimir los valores, refactorizar cualquier código de Bash que tenga en Awk suele ser un mejor enfoque que hacer este procesamiento en Bash.

0
tripleee 17 sep. 2018 a las 08:22