¿Cómo puedo agregar una cadena aleatoria para cada línea?

12

Estoy tratando de agregar una cadena aleatoria para cada línea mientras se ejecuta:

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

Antes de eso, se genera la cadena aleatoria:

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

El problema es que imprimirá la misma cadena aleatoria para cada línea:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

¿Qué debo hacer para obtener diferentes cadenas aleatorias para cada línea?

usuario134969
fuente
En lugar de alguna variación de tr -dc '[:alnum:]' </dev/urandom | head -c 6, sería más simple y computacionalmente más eficiente de usar pwgen -s 6 1, o mejor aún, pwgen -s 6 $(wc -l myfile)le dará exactamente todas las cadenas aleatorias que necesita, de una sola vez.
user1404316

Respuestas:

9

Con función awk system() :

Muestra input.txt:

a
b
c

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

Salida de muestra:

nameSDbQ7T-a
nameAliHY0-b
nameDUGP2S-c

system(command)
Ejecute el comando del sistema operativo commandy luego regrese al programa awk

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

RomanPerekhrest
fuente
Bien, pero ¿por qué me estoy poniendo tr: write error: Broken pipe?
user134969
@ user134969, funciona bien. Asegúrese de no haber cometido ningún error en la línea de comando
RomanPerekhrest
9

¿No crees que es un poco obvio? ¡Solo está generando una cadena aleatoria una vez y la almacena en ranvariable y la usa para todas las líneas!

Utilizando getlineen una variable de una tubería

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

Cuando lo usa command | getline var, la salida del comando se envía a través de una tubería hacia getline()y dentro de la variable var.

También tenga en cuenta que cuando se abre una tubería para salida, awkrecuerda el comando asociado con él y las escrituras posteriores al comando se agregan a las escrituras anteriores. Necesitamos hacer una close()llamada explícita del comando para evitar eso.

Si las comillas simples anidadas en el str_generatorestán causando un problema, reemplace con su 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
fuente
8

Ejecutar una instancia de tr -dc '[:alnum:]' </dev/urandom | head -c 6por línea de entrada sería contraproducente, sería mejor hacerlo:

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

Si su entrada no contiene backticks ni comillas simples, también puede usar m4's mkstemp():

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

Esta variación en un par de las otras respuestas hace la generación de cadenas aleatorias fuera 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

La canalización tr+ foldgenera un flujo interminable de cadenas aleatorias de seis caracteres en la entrada estándar de awk. awkignorará la entrada estándar si se proporciona un nombre de archivo, por lo que estas cadenas aleatorias se leen getlinedesde /dev/stdindentro de la variable r. printfluego se usa para prefijar las líneas del archivo con la cadena apropiada.

Dado el archivo

123
abc
@#$

esto puede producir

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

Sin usar awk en absoluto, simplemente simple bash

while read line; do
    printf "name%s-%s\n" \
        "$(tr -dc '[:alnum:]' </dev/urandom|head -c6)" \
        "$line"
done <myfile
Rico
fuente
1
El problema con esto es que puede corromper los datos leídos del archivo. Ver unix.stackexchange.com/questions/209123/…
Kusalananda
0
paste <(base64 -w6 /dev/urandom) input.txt | awk 'NF==2{print $1$2} NF!=2{exit}'

Requisitos : el input.txt debe contener solo una columna, en otras palabras, no debe tener tabulaciones o espacios, ya que se utilizan como separador predeterminado por awky paste(solo caracteres de tabulación) comandos. De lo contrario, el comando debe modificarse un poco.

Nota: El alfabeto Base64 contiene +y /caracteres: tabla Base64 , si solo desea números y letras, puede usar el base32comando - Alfabeto Base32 .

Entrada

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

=== caracteres añadidos para mayor claridad.

Salida

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