Wie kann ich eine zufällige Zeichenfolge für jede Zeile hinzufügen?

12

Ich versuche, zufällige Zeichenfolge für jede Zeile beim Ausführen hinzuzufügen:

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

Vorher wird der Zufallsstring generiert:

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

Das Problem ist, dass für jede Zeile dieselbe zufällige Zeichenfolge ausgegeben wird:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

Was kann ich tun, um für jede Zeile eine andere zufällige Zeichenfolge zu erhalten?

user134969
quelle
Anstatt eine Variation von zu verwenden tr -dc '[:alnum:]' </dev/urandom | head -c 6, wäre es einfacher und rechnerisch effizienter pwgen -s 6 1, oder besser pwgen -s 6 $(wc -l myfile), Sie erhalten genau alle zufälligen Zeichenfolgen, die Sie benötigen, auf einen Schlag.
user1404316

Antworten:

9

Mit awk- system() Funktion:

Probe input.txt:

a
b
c

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

Beispielausgabe:

nameSDbQ7T-a
nameAliHY0-b
nameDUGP2S-c

system(command)
Führen Sie den Betriebssystembefehl aus commandund kehren Sie dann zum awk-Programm zurück

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

RomanPerekhrest
quelle
Schön, aber warum bekomme ich tr: write error: Broken pipe?
user134969
@ user134969, es funktioniert gut.
Stellen
9

Findest du das nicht ein bisschen offensichtlich? Sie generieren nur eine zufällige Zeichenfolge und speichern sie in einer ranVariablen und verwenden sie für alle Zeilen!

Verwendung getlinein eine Variable aus einer 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

Wenn Sie verwenden command | getline var, wird die Ausgabe des Befehls über eine Pipe an getline()und in die Variable gesendet var.

Beachten Sie auch, dass beim Öffnen einer Pipe für die Ausgabe awkder zugehörige Befehl gespeichert und nachfolgende Schreibvorgänge an die vorherigen Schreibvorgänge angehängt werden. Wir müssen close()den Befehl explizit aufrufen, um dies zu verhindern.

Wenn die verschachtelten einfachen Anführungszeichen in den str_generatorein Problem verursachen, ersetzen Sie sie durch das entsprechende Oktal ( \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
quelle
8

Das Ausführen einer Instanz von tr -dc '[:alnum:]' </dev/urandom | head -c 6pro Eingabezeile wäre kontraproduktiv. Am besten tun Sie Folgendes:

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

Wenn Sie Ihre Eingabe enthält keine Backticks noch einfache Anführungszeichen, können Sie auch nutzen m4‚s mkstemp():

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

Diese Variation einiger anderer Antworten bewirkt die Zufallsgenerierung von Zeichenfolgen außerhalb von 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

Die tr+ fold-Pipeline generiert bei der Standardeingabe von einen endlosen Strom zufälliger sechsstelliger Zeichenfolgen awk. awkignoriert die Standardeingabe, wenn ein Dateiname angegeben wird, sodass diese zufälligen Zeichenfolgen getlinevon /dev/stdinin die Variable eingelesen werden r. printfwird dann verwendet, um den Zeilen aus der Datei den entsprechenden String voranzustellen.

Angesichts der Datei

123
abc
@#$

dies kann produzieren

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

Ganz ohne awk, ganz einfach bash

while read line; do
    printf "name%s-%s\n" \
        "$(tr -dc '[:alnum:]' </dev/urandom|head -c6)" \
        "$line"
done <myfile
Reich
quelle
1
Das Problem dabei ist, dass Sie möglicherweise die aus der Datei gelesenen Daten beschädigen. Siehe unix.stackexchange.com/questions/209123/…
Kusalananda
0
paste <(base64 -w6 /dev/urandom) input.txt | awk 'NF==2{print $1$2} NF!=2{exit}'

Anforderungen - Die Datei input.txt sollte nur eine Spalte enthalten, dh keine Tabulatoren oder Leerzeichen enthalten, da sie als Standardtrennzeichen für die Befehle awkund paste(nur Tabulatorzeichen) verwendet werden. Andernfalls muss der Befehl ein wenig geändert werden.

Hinweis: Das Base64- Alphabet enthält +und /Zeichen: Base64-Tabelle . Wenn Sie nur Zahlen und Buchstaben möchten, können Sie den base32Befehl " Base32-Alphabet" verwenden .

Eingang

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

=== Zeichen zur Verdeutlichung hinzugefügt.

Ausgabe

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