Usando sed para substituir um *grande* número de variáveis ​​em um arquivo

Usando sed para substituir um *grande* número de variáveis ​​em um arquivo

Eu tenho um grande número de arquivos de log, em uma caixa Linux, preciso limpar dados confidenciais antes de enviá-los a terceiros. Eu usei o script abaixo em ocasiões anteriores para realizar esta tarefa e funcionou perfeitamente (o script foi construído com alguma ajuda daqui :-)):

#!/bin/bash

help_text () {
cat <<EOF
Usage: $0 [log_directory] [client_name(s)]
EOF
exit 0
}

CMDLINE=""$0" "$@""
if [ -z "$1" ]; then
        help_text
else

        pattern=""
        delim=""
        n=1

        counter=`find "$1" -name *.gz |sort |wc -l`

        BAKIFS=$IFS
        IFS=$(echo -en "\n\b")
        exec 3<&0
        exec 0<"$2"
        while read -r line
        do
                pattern=$pattern$delim$line
                delim="|"
        done
        exec 0<&3
        IFS=$BAKIFS

        while [ $n -lt $counter ]
        do
                for i in `find "$1" -name *.gz |sort`
                do
                        gunzip "$i"
                        i_unzip=$(echo "$i" |sed 's/\.[^\.]*$//')
                        sed -ri "s/$pattern/CLIENT/g" "$i_unzip"
                        gzip "$i_unzip"
                done
                n=n+1
        done
fi
exit 0

No entanto, agora um de nossos departamentos me enviou um CLIENT_FILE.txt com425.000+variáveis! Acho que posso ter atingido algum limite interno! Se alguém tiver uma idéia de como lidar com tantas variáveis, eu realmente apreciaria.

Tentei dividir o arquivo do cliente em 4 com cerca de 100.000 variáveis ​​em cada, mas ainda não funciona. Detesto continuar dividindo, pois tenho 20 diretórios com até 190 arquivos em cada diretório para percorrer. Quanto mais arquivos de cliente eu fizer, mais passagens terei que fazer.

Responder1

Eu tentaria algo assim:

#!/bin/bash

files=()
while read file; do
    gunzip "$file"  &&  files+=( "${file%.gz}" )
done < <(find "$1" -name '*.gz')

awk '
    FILENAME == ARGV[1] {
        client_name[$0]++
        next
    }
    FNR == 1 {
        output = FILENAME ".new"
    }
    {
        for (i=1; i<=NF; i++) {
            if ($i in client_name)
                $i = "CLIENT"
        }
        print > output
    }
' "$2" "${files[@]}"

for file in "${files[@]}"; do
    mv "$file" "$file.old"  &&
    mv "$file.new" "$file"  &&
    gzip "$file"
done

Se seus arquivos de log tiverem algo além de simples linhas delimitadas por espaço, o script awk poderá atrapalhar a formatação.

Responder2

Você deve tentar escrever o sedpadrão em um arquivo e passá-lo sedcom a opção --file=. Os parâmetros da linha de comando não se destinam a transmitir grandes blocos de dados.

informação relacionada