Yo no soy programador, pero desarrollé un script de shell para leer un archivo posicional y, basado en una sola letra especificada en la posición 16, copie toda la línea a otro archivo.

Ejemplo:

ARCHIVO DE ENTRADA
003402841000011 A 10CNPJ08963394000195
003402841000041 B 20CNPJ08963394000195 16012020XX5313720087903007 003402841000011 A 10CNPJ08963394000195
003402841000041 B 20CNPJ08963394000195 16012020XX5313720087903007

ARCHIVO DE SALIDA A
003402841000011 A 10CNPJ08963394000195
003402841000011 A 10CNPJ08963394000195

ARCHIVO DE SALIDA B
003402841000041 B 20CNPJ08963394000195 16012020XX5313720087903007 003402841000041 B 20CNPJ08963394000195 16012020XX5313720087903007

El código que tengo actualmente:

#!/usr/bin/env bash

ARQ_IN="$1";
DIR_OUT="C:/Users/etc/etc/";

while IFS= read -r line || [[ -n "$line" ]]; 
do 

SUBSTRING=$(echo $line| cut -c16);

if [ $SUBSTRING == "A" ]
then
    echo "$line" >> "$DIR_OUT"arqA.txt;
else
    if [ $SUBSTRING == "B" ]
    then
        echo "$line" >> "$DIR_OUT"arqB.txt;
    else
        if [ $SUBSTRING == "K" ]
        then
            echo "$line" >> "$DIR_OUT"arqK.txt;
        else
            if [ $SUBSTRING == "1" ]
            then
                echo "$line" >> "$DIR_OUT"arq1.txt;
            else
            
            fi
        fi
    fi
fi


done < "$ARQ_IN"

Aunque este código funciona, no funciona a la velocidad que necesito, el INPUT FILE tiene alrededor de 400k registros.

¿Alguien puede ayudarme a escribir un nuevo código o mejorar este?

2
Icaro Americo 2 dic. 2020 a las 22:39

2 respuestas

La mejor respuesta

Este es un trabajo para awk, podría intentar seguirlo, aunque no lo he probado con un conjunto de datos enorme, pero definitivamente debería ser más rápido que el enfoque actual de OP. Para agregar una ruta completa antes del nombre del archivo de salida, podríamos pasar la variable de shell a la variable awk y obtenerla en la variable outputFile aquí.

awk '
{
  close(outputFile)
  outputFile=("output_file_"substr($0,16,1))
  print >> (outputFile)
}
' Input_file

Con la ruta completa de la carpeta para guardar los archivos, cambie /tmp/test/ con su ruta real aquí.

DIR_OUT="/tmp/test/"
awk -v folder="${DIR_OUT}" '
{
  close(outputFile)
  outputFile=(folder"arq"substr($0,16,1)".txt")
  print >> (outputFile)
}
' Input_file
4
RavinderSingh13 2 dic. 2020 a las 20:01

Sí, los bucles while-read de bash pueden ser bastante lentos, y además no es necesario llamar a cut para obtener una subcadena. Prueba esto:

while IFS= read -r line || [[ -n "$line" ]]; do 
    # the offset is zero-based, so use 15 not 16
    letter=${line:15:1}
    case "$letter" in
        [ABK1]) echo "$line" >> "${DIR_OUT}arq${letter}.txt" ;;
    esac
done < "$ARQ_IN"

Con if-else if en cascada, use elif

if some condition; then
    some action
elif some other condition; then
    some other action
...
else
    some default action
fi
2
glenn jackman 3 dic. 2020 a las 03:10