Bastante nuevo en la programación AWK. Tengo un archivo1 con entradas como:
15>000000513609200>000000513609200>B>I>0011>>238/PLMN/000100>File Ef141109.txt>0100-75607-16156-14 09-11-2014 15>000000513609200>000000513609200>B>I>0011>Danske Politi>238/PLMN/000200>>0100-75607-16156-14 09-11-2014 15>000050354428060>000050354428060>B>I>0011>Danske Politi>238/PLMN/000200>>4100-75607-01302-14 31-10-2014Quiero escribir un script awk, donde si el segundo campo restado del tercer campo es un 0, entonces imprime el campo 2. De lo contrario, si la (diferencia> 0), imprime todos los dígitos intermedios incrementados en 1 a partir del segundo campo que termina en 3er campo. No habrá ningún escenario en el que el tercer campo sea menor que el segundo. Así que ignorando esa condición.
Estaba haciendo algo como:
awk 'NR > 2 { print p } { p = $0 }' file1 | awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'((Alguien me dijo que awk está cerca de C en términos de sintaxis))
Pero a partir de la salida, me parece que las conversiones de Cadena a numérico o de numérico a cadena no se están realizando en el lugar correcto en el momento correcto. ¿No debería ser atendido por AWK automáticamente?
La SALIDA que obtengo:
513609200 513609201 513609200Lo cual no es tan silencioso como se esperaba. Un problema evidente es que ignora los 0 anteriores.
Amablemente ayúdeme a modificar el script AWK para obtener el resultado deseado.
NOTA:
awk 'NR > 2 { print p } { p = $0 }' file1 es solo para eliminar la primera y última entrada en mi file1 original. Así que la parte que necesita ser arreglada es:
awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'En awk, piense en $ como un operador para recuperar el valor del número de campo nombrado ($0 es un caso especial)
$1 es el valor del campo 1$NF es el valor del campo dado en la variable NF Entonces, $($3 - $2) intentará obtener el valor del número de campo dado por la expresión ($3 - $2).
Necesitas menos signos $
awk -F">" '{ if ($3 == $2) print $2 else { v=$2 while (v < $3) print v++ } }'Normalmente, esto funcionará, pero sus números están más allá de los límites de enteros awk , por lo que necesita otra solución para manejarlos. Estoy publicando esto para iniciar otras soluciones e ilustrar mejor sus especificaciones.
$ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' filetenga en cuenta que esto omitirá las filas que dice que es imposible que suceda
Un ejemplo a pequeña escala
$ cat file_0 x>1000>1000>etc x>2000>2003>etc x>3000>2999>etc $ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file_0 1000 2000 2001 2002 2003 Aparentemente, las versiones más nuevas de gawk tienen opciones --bignum para enteros de precisión arbitraria, si tiene una versión compatible que puede resolver su problema pero no tengo acceso para verificar.
Para cualquiera que no tenga acceso inmediato a gawk con soporte de bigint, puede ser más sencillo considerar otras opciones si se requiere algún tipo de soporte de "entero grande". Dado que Ruby tiene un modo de operación extraño, consideremos Ruby aquí.
Para comenzar, solo hay cuatro cosas que debe recordar:
Así una traducción directa de:
awk -F'>' '{for(i=$2;i<=$3;i++) print i}' filesería:
ruby -an -F'>' -e '($F[1].to_i .. $F[2].to_i).each {|i| puts i }' filePara protegerse de las líneas vacías, el siguiente script sería un poco mejor:
($F[1].to_i .. $F[2].to_i).each {|i| puts i } if $F.length > 2Esto podría llamarse como se indicó anteriormente, o si el script está en un archivo (digamos script.rb) usando el conjuro:
ruby -an -F'>' script.rb fileDados los datos de entrada OP, la salida es:
513609200 513609200 50354428060El relleno izquierdo se puede lograr de varias maneras; consulte, por ejemplo, esta página SO .