usando sed para substituir o padrão por valores hash

4

Eu quero pesquisar o arquivo e substituir padrão específico por seus valores de hash (SHA1).

Por exemplo, deixe file.txt ter o seguinte conteúdo:

one S56G one two three
four five V67X six

e quero substituir o padrão [A-Z][0-9]\{2\}[A-Z] pelo valor SHA1 da correspondência. No exemplo acima, as correspondências são S56G e V67X .

Usando sed , tentei:

sed "s/[A-Z][0-9]\{2\}[A-Z]/$(echo \& | sha1sum)/g"

sem sucesso, pois o resultado é sempre o valor hash de '&' .

Eu também tentei ge flag, com o comando:

sed 's/[A-Z][0-9]\{2\}[A-Z]/echo & | sha1sum/ge'

que gera erros:

sh: 1: one: not found
sha1sum: one: No such file or directory
sha1sum: two: No such file or directory
sha1sum: three: No such file or directory

    
por user1734905 25.10.2013 / 11:04

3 respostas

7

Em sua tentativa, a substituição do comando ( $(…) ) é executada antes de sed ser executado e a string passada para ele como parâmetro.

Use uma linguagem de script cuja substituição de expressão regular suporte a execução de código:

perl -MDigest::SHA=sha1_hex -pe 's/[A-Z][0-9]{2}[A-Z]/sha1_hex$&/ge' inputfile

php -R 'echo preg_replace("/[A-Z][0-9]{2}[A-Z]/e","sha1(\
perl -MDigest::SHA=sha1_hex -pe 's/[A-Z][0-9]{2}[A-Z]/sha1_hex$&/ge' inputfile

php -R 'echo preg_replace("/[A-Z][0-9]{2}[A-Z]/e","sha1(\%pre%)",$argn),"\n";' inputfile

ruby -rdigest/sha1 -pe '$_.gsub!(/[A-Z][0-9]{2}[A-Z]/){Digest::SHA1.hexdigest$&}' inputfile

python -c 'import sys,fileinput,re,hashlib;[sys.stdout.write(re.sub("[A-Z][0-9]{2}[A-Z]",lambda s:hashlib.sha1(s.group(0)).hexdigest(),l))for l in fileinput.input()]' inputfile
)",$argn),"\n";' inputfile ruby -rdigest/sha1 -pe '$_.gsub!(/[A-Z][0-9]{2}[A-Z]/){Digest::SHA1.hexdigest$&}' inputfile python -c 'import sys,fileinput,re,hashlib;[sys.stdout.write(re.sub("[A-Z][0-9]{2}[A-Z]",lambda s:hashlib.sha1(s.group(0)).hexdigest(),l))for l in fileinput.input()]' inputfile
    
por 25.10.2013 / 11:32
1

@manatowork certamente forneceu uma resposta. Apenas adicionando isso como uma curiosidade ...

Uma variante bash + sha1sum.

function fail()
{
    printf "Failed on line \'%s'\n" "$line" >&2
    exit 2
}

declare -A sha_map;
re='[A-Z][0-9]{2}[A-Z]';

while read -r line; do
    while [[ $line =~ $re ]]; do
        m="${BASH_REMATCH[0]}";
        if ! [[ ${sha_map[$m]} ]]; then
            sha="$(printf "%s" "$m" | sha1sum)" || fail;
            sha_map["$m"]=${sha%% *};
        fi
        line=${line//$m/${sha_map[$m]}};
    done
    printf "%s\n" "$line";
done <"$fn"
    
por 25.10.2013 / 13:19
-1

Aqui está a minha solução:

cp file.txt result.txt
cat file.txt | grep -o '[A-Z][0-9]\{2\}[A-Z]' | while read i ; do
    sed -i "s/$i/$(echo -n $i | sha1sum | cut -f 1 -d ' ')/g" result.txt
done

Copie todas as linhas e cole-as no terminal. Com file.txt

one S56G one two three
four five V67X six

Eu obtenho

one 03763566330069a397584344c0a640a3cba05a4c one two three
four five 7802350a2592cdc6dfdee408336919ee9e3cc5f2 six

Esta solução tem uma complexidade de O (n ^ 2) e não se destina a ser usada em arquivos grandes com muitas correspondências de padrões, já que processa os arquivos de destino por correspondência de padrões.

    
por 25.10.2013 / 11:21