substitui a coluna inteira em um arquivo com uma string aleatória

7

Qual é a maneira mais fácil de substituir uma coluna em um arquivo? Basicamente, meu file.txt tem 3 colunas separadas por , .

Como posso alterar a segunda coluna com um script bash?

SveUJW24ibppfePgYeYHz7fC0,64BzZdqrYY7Tx8sbj5tmEW,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,gTdmvjmahIOoyzmrttVMvTc1ER0bt,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,LzLtoEg18E1brm66dPjcHZfpI107nn4h,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
7cjW5DZlXw1LYzVugbVyqfxRX,i7B4Q9w8h5anmMW87DfIBEm0AuNjbLGq,XttE1In9eZQ8puJVUriuNvx2AJAxviGf
XiLE8r9AMqy5YZQ9BbIS6m559,ToT2wbQdpNNySPxP1Tgz1,DssiszVBa05pbVDSOXNRaFXRxw0eZKHf
Sygrl5287BViOn0uQ9uCYipB1,TEYnXl6APWGbm9ckLCcHFUJzk7qS8JXH,sD2O46sbh1yVIluoyn6Zm2OKXYe05vV9
Qi6DxJ96M0hxNe4cgux3iJ1aS,LK3GHTpuo9kbmK9McRN4sFRQTGh2DU8J,wk2eF3f9xk5HowLzDIL3hCCNSmx8Uwi8
ZIX7qp5IIPekA0kzBdFR4IUQZ,9m9lEjfiotQ97s3uVN8EEP7Y1JmpgAk7,99ilfJWoJEBsKOfYI3buFfher07OCz6Y

Atualizar substitua por outra string em uma variável. digamos var=new-sting .

Na verdade, eu estava pensando que poderia fazer algo assim:

sed "s/,[^,]*/,$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)/" file.txt

Mas não está funcionando como esperado. Eu estou tendo a mesma corda repetidamente.

    
por dmx 19.05.2017 / 11:01

3 respostas

6

Supondo que file.txt contenha linhas de texto divididas em três colunas com vírgulas e que não haja vírgulas adicionais em nenhum lugar, então cada linha tem exatamente duas delas:

replacement="my string"
sed "s/,.*,/,$replacement,/" file.txt

Saída:

SveUJW24ibppfePgYeYHz7fC0,my string,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,my string,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,my string,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
7cjW5DZlXw1LYzVugbVyqfxRX,my string,XttE1In9eZQ8puJVUriuNvx2AJAxviGf
XiLE8r9AMqy5YZQ9BbIS6m559,my string,DssiszVBa05pbVDSOXNRaFXRxw0eZKHf
Sygrl5287BViOn0uQ9uCYipB1,my string,sD2O46sbh1yVIluoyn6Zm2OKXYe05vV9
Qi6DxJ96M0hxNe4cgux3iJ1aS,my string,wk2eF3f9xk5HowLzDIL3hCCNSmx8Uwi8
ZIX7qp5IIPekA0kzBdFR4IUQZ,my string,99ilfJWoJEBsKOfYI3buFfher07OCz6Y

Isso processará todas as linhas de uma vez e substituirá a coluna do meio pelo mesmo valor a cada vez. O conteúdo alterado será impresso no terminal por padrão, se você quiser modificar file.txt no lugar, escreva sed -i em vez de sed .

Se você precisar atualizar a variável de substituição para cada linha de qualquer forma (aqui uma nova string aleatória para cada linha), você pode fazer um loop sobre as linhas da seguinte forma:

while read line ; do
    replacement="random number $RANDOM"
    sed "s/,.*,/,$replacement,/" <<< "$line"
done < file.txt

Exemplo de saída:

SveUJW24ibppfePgYeYHz7fC0,random number 27584,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,random number 2959,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,random number 5463,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
7cjW5DZlXw1LYzVugbVyqfxRX,random number 12889,XttE1In9eZQ8puJVUriuNvx2AJAxviGf
XiLE8r9AMqy5YZQ9BbIS6m559,random number 3754,DssiszVBa05pbVDSOXNRaFXRxw0eZKHf
Sygrl5287BViOn0uQ9uCYipB1,random number 25375,sD2O46sbh1yVIluoyn6Zm2OKXYe05vV9
Qi6DxJ96M0hxNe4cgux3iJ1aS,random number 5284,wk2eF3f9xk5HowLzDIL3hCCNSmx8Uwi8

É provavelmente a maneira mais fácil de colocar este snippet de código em um arquivo de script e, em seguida, você executou o redirecionamento de sua saída para um novo arquivo separado (não o arquivo original a partir do qual você leu!) assim:

bash my-replacement-script.sh > new-file.txt
    
por Byte Commander 19.05.2017 / 11:27
6

Eu sugeriria uma abordagem baseada no perl Módulo Bytes :: Random :: Secure , baseado em Preenchendo a coluna do arquivo de texto com dados aleatórios usando o bash modificado para usar sua mistura desejada de letras maiúsculas e minúsculas e dígitos decimais:

perl -MBytes::Random::Secure=random_string_from -F, -ane '
  BEGIN{$chars = join "", ("a".."z","A".."Z",0..9)}
  $F[1] = random_string_from($chars, 32);
  print join ",", @F
' file

Como alternativa, se você quiser usar o /dev/urandom pipeline, uma maneira de fazer isso sem loop externo seria usar um FIFO com a função getline do awk:

  1. faz o FIFO $ mkfifo _fifo

  2. execute seu comando, transmitindo sua saída para o FIFO

    $ cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 > _fifo &
    

    ou (eliminando o uso inútil do gato )

    $ tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32 > _fifo &
    
  3. obtém linhas do FIFO e as substitui nas linhas do arquivo de destino

    $ awk '{getline  < "_fifo"} 1' FS=, OFS=, file
    
  4. remova o FIFO

    rm _fifo
    

Teste:

$ mkfifo _fifo
$ tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32 > _fifo &
[1] 5815
$ awk '{getline  < "_fifo"} 1' FS=, OFS=, file
SveUJW24ibppfePgYeYHz7fC0,hpqBxCOYIj7eQ9MgbPNG69SY3X3iAJ7A,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,ACU1hyR8zGRfDMeUk4a6TFVcQvUAtZog,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,dkeKUnMYZepGcGMgdQc9IORa77Vtwr7w,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
7cjW5DZlXw1LYzVugbVyqfxRX,UMjkPZAB3ElpOnXWnsQe9w1v0h6HMLPs,XttE1In9eZQ8puJVUriuNvx2AJAxviGf
XiLE8r9AMqy5YZQ9BbIS6m559,iz5tavnYqajwTokPCM4HJIsZlIloLcVy,DssiszVBa05pbVDSOXNRaFXRxw0eZKHf
Sygrl5287BViOn0uQ9uCYipB1,RHPFMgKoIGojvM6aTwb43lH4BAr8Jh5Y,sD2O46sbh1yVIluoyn6Zm2OKXYe05vV9
Qi6DxJ96M0hxNe4cgux3iJ1aS,fqTsEPr3PIPqIWPrb2uIl47QjXlSt3gL,wk2eF3f9xk5HowLzDIL3hCCNSmx8Uwi8
ZIX7qp5IIPekA0kzBdFR4IUQZ,uAFKvX5z2ik2i1AKh3wYp503xpNy8dxA,99ilfJWoJEBsKOfYI3buFfher07OCz6Y
rm _fifo
[1]+  Broken pipe             cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 > _fifo

Com o GNU awk, você pode fazer o equivalente internamente usando getline com um co-processo :

$ gawk '{"tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32" |& getline } 1' FS=, OFS=, file 
SveUJW24ibppfePgYeYHz7fC0,hKOYDf6lgEtVwzJvCl34eYu22m5bZ11e,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,bV9m4OgbTzDTJQanhS3BTmxr5gUcouDy,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,r9850TtXPJsLLNMupiwSPsqx7ovtb5ph,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
7cjW5DZlXw1LYzVugbVyqfxRX,aRRVAecWxeTtt3WX36MIoFlMCvDcFb3a,XttE1In9eZQ8puJVUriuNvx2AJAxviGf
XiLE8r9AMqy5YZQ9BbIS6m559,BeCoCV4kMb8FUt6Y3RFxolI2CKqzbeuO,DssiszVBa05pbVDSOXNRaFXRxw0eZKHf
Sygrl5287BViOn0uQ9uCYipB1,WZ0hSxurp22dCdhV12Gjcms6rdx8hjM2,sD2O46sbh1yVIluoyn6Zm2OKXYe05vV9
Qi6DxJ96M0hxNe4cgux3iJ1aS,ujxdLQZo1vkCZnkUej6pLjZxVmN7XiTE,wk2eF3f9xk5HowLzDIL3hCCNSmx8Uwi8
ZIX7qp5IIPekA0kzBdFR4IUQZ,qxp3dwltN5Mxfece27Zvq2NqbjPlF358,99ilfJWoJEBsKOfYI3buFfher07OCz6Y
    
por steeldriver 19.05.2017 / 12:08
3

Usando awk :

awk -v var="mystring" -F, 'BEGIN {OFS = FS} { = var; print}'
  • -v : crie uma variável chamada var que contenha a string "mystring"
  • -F, : use , como separador de campo
  • BEGIN {OFS = FS} define o separador de campo de saída igual ao separador de campo para manter o separador (vírgula) após a substituição
  • { = var; print} substitui o campo 2 (coluna 2) por var content; depois imprima.

Você também pode alterar -v var="mystring" com algo como -v var="$variable" , que $variable é uma variável em seu ambiente.

Aqui está um exemplo:

veUJW24ibppfePgYeYHz7fC0,64BzZdqrYY7Tx8sbj5tmEW,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,gTdmvjmahIOoyzmrttVMvTc1ER0bt,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,LzLtoEg18E1brm66dPjcHZfpI107nn4h,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ

vamos executar o comando:

$ awk -v var="HERE-IS-MY-STRING" -F, 'BEGIN {OFS = FS} { = var; print}' file.tx

veUJW24ibppfePgYeYHz7fC0,HERE-IS-MY-STRING,yL6mCP0Do28k4EoTZUfKfqNYiIhGxxkA
xyRG8Da6kY35xeIT492Lul7xu,HERE-IS-MY-STRING,ne6RIM2TeMQAax1GgzL7FeDrnQyHPH1i
sxTf13KlAnjtXodJouQ9V6m5b,HERE-IS-MY-STRING,GUnApYwwDCZxWGZtzKzTU6sJRgHlUUfQ
    
por Ravexina 19.05.2017 / 11:31