Extraer columnas de un archivo de texto sin delimitadores

1

Tengo un archivo de texto grande que es básicamente una secuencia de datos comprimidos en conjunto para cada fila. Me han pedido que analice el fallo de ciertos datos en algunas columnas. Los datos no están delimitados de ninguna manera. Sin embargo, tengo una lista de longitudes de "columna" y comentarios sobre si hay datos relevantes en cada "columna".

Usaría Excel, pero el límite de Excel para delimitar por columnas está restringido a 1000 caracteres por fila, y cada fila va mucho más allá de esto. Varios de estos campos tienen cadenas de 30 espacios que actúan como relleno y hay al menos unos 15 de estos ... Espero analizar estos campos designados "vacíos".

Lo que necesito es una forma en que pueda alimentar mi archivo y con una matriz que pueda proporcionar que tenga las longitudes de columna y tal vez un marcador como "X" para ignorar las columnas respectivas que quiero ignorar, hacer que escupe un nuevo archivo con delimitadores, que luego puedo alimentar a Excel para su análisis.

Por ejemplo, si tuviera un archivo con una fila como aaaaaabbbbbccccdddddeeeffffffy alimente este archivo con una matriz [6 5 4X 5 3X 6], escupiría un archivo con aaaaaa^bbbbb^ddddd^ffffffesa fila.

¿Hay alguna manera esto se puede hacer con grep, awko sed?

Gracias por adelantado.

Eliseo d'Annunzio
fuente
¿Quieres ^ser el delimitador exacto en las filas resultantes?
RomanPerekhrest
Era un personaje arbitrario que usé, ¡pero estaría bien!
Eliseo d'Annunzio

Respuestas:

1

Si tiene GNU awk, puede especificar anchos de campo explícitos, por ejemplo

$ printf 'aaaaaabbbbbccccdddddeeeffffff\n' | 
    gawk -v FIELDWIDTHS="6 5 4 5 3 6" -v OFS="^" '{print $1, $2, $4, $6}'
aaaaaa^bbbbb^ddddd^ffffff

A partir de la versión 4.2, puede omitir caracteres utilizando una n:msintaxis, por ejemplo

printf 'aaaaaabbbbbccccdddddeeeffffff\n' |
   gawk -v FIELDWIDTHS="6 5 4:5 3:6" -v OFS="^" '{$1=$1} 1'
aaaaaa^bbbbb^ddddd^ffffff

(el $1=$justo fuerza la reevaluación de $0con los anchos de campo especificados).

Consulte, por ejemplo, la Guía del usuario de GNU Awk: 4.6 Lectura de datos de ancho fijo

conductor de acero
fuente
Esto está más cerca de lo que tenía en mente ... ¡Gracias!
Eliseo d'Annunzio
5

cutEnfoque de comando corto :

input.txtContenido de muestra :

aaaaaabbbbbccccdddddeeeffffff
wwwwwwddddd111133333xxxaaaaaa
ffffff00000sssszzzzz000rrrrrr

El trabajo:

cut -c 1-6,7-11,16-20,24-29 --output-delimiter=^ input.txt
  • -c - para seleccionar solo personajes

  • 1-6,7-11,16-20,24-29 - rangos consecutivos de posiciones de personajes, ajustables de forma flexible

  • --output-delimiter=^ - delimitador de campo de salida, puede ajustarlo a lo que quiera


La salida:

aaaaaa^bbbbb^ddddd^ffffff
wwwwww^ddddd^33333^aaaaaa
ffffff^00000^zzzzz^rrrrrr
RomanPerekhrest
fuente
Error de poste de cerca . Los números -c 1-6,7-12,17-22,26-31no coinciden con la salida, por ejemplo, con los números de la primera línea de salida sería: aaaaaa^bbbbbc^ddddee^ffff.
agc
1

Es difícil de decir sin ver su entrada exacta y la salida deseada, pero ...

sed -e "$(
  printf '%d\n' 6 5 4 5 3 6 |
    awk '
      {
        f[NR] = f[NR-1] + $1
      }
      END {
        for (i=NR; i>0; i--) {
          printf "s/./&^/%d\n", f[i]
        }
      }
    '
)" infile.txt | cut -d^ -f1,2,4,6

No probado Sin errores, lo prometo. ;)


Bien, lo probé. Me faltaba la llave final END. No hay otros errores. Funciona perfectamente en entrada de ejemplo. Salida es:

aaaaaa^bbbbb^ddddd^ffffff
Comodín
fuente
0

Con sed, uno podría escribir (usando _como delimitador):

sed "$(echo s/./\&_/{29,23,20,15,11,6}\;)"

Pero esto significa resumir las posiciones absolutas de los anchos de columna. Para usar directamente los anchos, necesitamos un escape feo para la sustitución del comando:

sed -E "s/./&_/6;$(echo s/.\*_\(.\)\{{5,4,5,3,6}\}/\&_/\;)"
Philippos
fuente
0

Versión mejorada de la cutrespuesta de RomanPerekhrest , con analizador de matriz de columnas, que incluye Xsufijos para mostrar cuántas columnas omitir.

Cargue la matriz $ny realice una función para analizar la matriz en números para cut -c:

n=(6 5 4X 5 3X 6)
col_array() { j=$(h=0; 
                  for f in $@; do 
                      g=${f/[Xx]};
                      i=$((h+1));
                      h=$((h+g));
                      [ $g = $f ] && echo -n $i-$h,
                  done;) ; 
              echo ${j%,}; }

El archivo input.txt contiene:

aaaaaabbbbbccccdddddeeeffffff
wwwwwwddddd111133333xxxaaaaaa
ffffff00000sssszzzzz000rrrrrr

Usar col_array()con cut:

cut -c $(col_array  ${n[@]}) --output-delimiter=^ input.txt

Salida:

aaaaaa^bbbbb^ddddd^ffffff
wwwwww^ddddd^33333^aaaaaa
ffffff^00000^zzzzz^rrrrrr

No hay una necesidad estricta de una matriz, ya que col_array()analiza sus parámetros:

cut -c $(col_array 3 5X 7) --output-delimiter=^ input.txt

Salida:

aaa^bbbcccc
www^ddd1111
fff^000ssss
agc
fuente