Como posso adicionar uma sequência aleatória para cada linha?

12

Estou tentando adicionar uma seqüência aleatória para cada linha durante a execução:

awk '{print "name" "'$ran'" "-"$0}' 'myfile'

Antes disso, a sequência aleatória é gerada:

ran="$(tr -dc '[:alnum:]' </dev/urandom | head -c 6)"

O problema é que ele imprimirá a mesma sequência aleatória para cada linha:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

O que devo fazer para obter uma sequência aleatória diferente para cada linha?

user134969
fonte
Em vez de algumas variações de tr -dc '[:alnum:]' </dev/urandom | head -c 6, seria mais simples e mais eficiente em termos de computação pwgen -s 6 1, ou melhor ainda pwgen -s 6 $(wc -l myfile), fornecerá exatamente todas as seqüências aleatórias necessárias, de uma só vez.
user1404316

Respostas:

9

Com a função awk system() :

Amostra input.txt:

a
b
c

awk '{ 
         printf "name";
         system("tr -dc \047[:alnum:]\047 </dev/urandom | head -c6");
         printf "-%s\n", $0
     }' input.txt

Saída de amostra:

nameSDbQ7T-a
nameAliHY0-b
nameDUGP2S-c

system(command)
Execute o comando do sistema operacional commande, em seguida, retorne ao programa awk

https://www.gnu.org/software/gawk/manual/gawk.html#index-system_0028_0029-function

RomanPerekhrest
fonte
Legal, mas por que estou recebendo tr: write error: Broken pipe?
user134969
@ user134969, funciona bem. Certifique-se de que você não cometeu nenhum erro na linha de comando
RomanPerekhrest
9

Você não acha que isso é óbvio? Você está apenas gerando uma sequência aleatória uma vez e armazenando-a em ranvariável e usando-a para todas as linhas!

Usando getlineem uma variável de um pipe

awk '{
     str_generator = "tr -dc '[:alnum:]' </dev/urandom | head -c 6"
     str_generator | getline random_str
     close(str_generator)
     print "name " random_str " - " $0
}' file

Quando você usa command | getline var, a saída do comando é enviada através de um canal para getline()a variável var.

Observe também quando um canal é aberto para saída, awklembra o comando associado a ele e as gravações subseqüentes no comando são anexadas às gravações anteriores. Precisamos fazer uma close()chamada explícita do comando para evitar isso.

Se as aspas simples aninhadas no str_generatorestão causando um problema, substitua pelo seu equivalente octal ( \047)

awk '{
     str_generator = "tr -dc \047[:alnum:]\047 </dev/urandom | head -c 6"
     str_generator | getline random_str
     close(str_generator)
     print "name " random_str " - " $0
}' file
Inian
fonte
8

A execução de uma instância de tr -dc '[:alnum:]' </dev/urandom | head -c 6cada linha de entrada seria contraproducente, seria melhor:

<input awk -v rng="LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | fold -w 6" '
  {rng | getline r; print "name"r"-"$0}'

Se sua entrada não contiver reticulares nem aspas simples, você também poderá usar m4's mkstemp():

<input sed "s/.*/mkstemp(name)\`&'/" | m4
Stéphane Chazelas
fonte
4

Essa variação em algumas das outras respostas gera a geração aleatória de cadeias fora de awk:

LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | fold -w 6 |
awk '{ getline r <"/dev/stdin"; printf("name%s-%s\n", r, $0) }' file

O pipeline tr+ foldgera um fluxo interminável de seqüências aleatórias de seis caracteres na entrada padrão de awk. awkignorará o padrão de entrada se um nome de ficheiro é fornecido, de modo que essas cadeias aleatórias são lidos getlinepela partir de /dev/stdindentro da variável r. printfé então usado para prefixar as linhas do arquivo com a sequência apropriada.

Dado o arquivo

123
abc
@#$

isso pode produzir

nameFI4L1S-123
name5S8Shr-abc
namebRUjzV-@#$
Kusalananda
fonte
1

Sem usar o awk, é simples bash

while read line; do
    printf "name%s-%s\n" \
        "$(tr -dc '[:alnum:]' </dev/urandom|head -c6)" \
        "$line"
done <myfile
Rico
fonte
1
O problema é que você pode corromper os dados lidos no arquivo. Veja unix.stackexchange.com/questions/209123/…
Kusalananda
0
paste <(base64 -w6 /dev/urandom) input.txt | awk 'NF==2{print $1$2} NF!=2{exit}'

Exigências - o input.txt deve conter apenas uma coluna, ou seja, não deve ter tabulações ou espaços, porque eles foram usados ​​como separador padrão por awke paste(apenas caractere de tabulação). Caso contrário, o comando deve ser modificado um pouco.

Nota: O alfabeto Base64 contém +e /caracteres: tabela Base64 , se você deseja apenas números e letras, pode usar o base32comando - alfabeto Base32 .

Entrada

===my_line_a
===my_line_b
===my_line_c
===my_line_d
===my_line_e

=== caracteres adicionados para maior clareza.

Resultado

LYSdm8===my_line_a
5sSSNt===my_line_b
YVMdkA===my_line_c
3b/nsT===my_line_d
xt/AZO===my_line_e
MiniMax
fonte