Jak mogę dodać losowy ciąg do każdej linii?

12

Próbuję dodać losowy ciąg dla każdej linii podczas działania:

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

Wcześniej generowany jest losowy ciąg:

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

Problem polega na tym, że wypisze ten sam losowy ciąg dla każdej linii:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

Co powinienem zrobić, aby uzyskać inny losowy ciąg dla każdej linii?

użytkownik134969
źródło
Zamiast niektórych odmian tr -dc '[:alnum:]' </dev/urandom | head -c 6, byłoby prostsze i bardziej wydajne obliczeniowo w użyciu pwgen -s 6 1, lub jeszcze lepiej pwgen -s 6 $(wc -l myfile)da dokładnie wszystkie losowe ciągi, których potrzebujesz, w jednym ujęciu.
użytkownik1404316,

Odpowiedzi:

9

Z funkcją awk system() :

Próbka input.txt:

a
b
c

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

Przykładowe dane wyjściowe:

nameSDbQ7T-a
nameAliHY0-b
nameDUGP2S-c

system(command)
Wykonaj polecenie systemu operacyjnego, commanda następnie wróć do programu awk

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

Roman Perekhrest
źródło
Fajnie, ale dlaczego dostaję tr: write error: Broken pipe?
user134969,
@ user134969, działa dobrze. Upewnij się, że nie popełniłeś żadnych błędów w linii poleceń
RomanPerekhrest
9

Nie uważasz, że to trochę oczywiste? Po prostu generujesz losowy ciąg jeden raz, przechowujesz go w ranzmiennej i używasz go dla wszystkich linii!

Używanie getlinedo zmiennej z potoku

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

Gdy używasz command | getline var, dane wyjściowe polecenia są przesyłane przez potok do getline()i do zmiennej var.

Zauważ też, że gdy potok jest otwarty dla danych wyjściowych, awkpamięta związane z nim polecenie, a kolejne zapisy do polecenia są dołączane do poprzednich zapisów. Musimy wykonać jawne close()wywołanie polecenia, aby temu zapobiec.

Jeśli zagnieżdżone pojedyncze cudzysłowy str_generatorpowodują problem, zamień na jego ósemkowy odpowiednik ( \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
źródło
8

Uruchomienie jednego wystąpienia tr -dc '[:alnum:]' </dev/urandom | head -c 6wiersza danych wejściowych przyniosłoby efekt przeciwny do zamierzonego, lepiej byłoby zrobić:

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

Jeśli wejście nie zawiera odwrócone, pojedyncze apostrofy ani apostrofów, można również użyć m4„s mkstemp():

<input sed "s/.*/mkstemp(name)\`&'/" | m4
Stéphane Chazelas
źródło
4

Ta odmiana kilku innych odpowiedzi powoduje losowe generowanie ciągu poza 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

tr+ foldRurociąg generuje niekończący się strumień losowych ciągów sześciu znaków na standardowe wejście awk. awkzignoruje standardowe wejście, jeśli podano nazwę pliku, więc te losowe ciągi znaków są odczytywane getlineze /dev/stdinzmiennej r. printfjest następnie używany do prefiksu wierszy z pliku odpowiednim ciągiem.

Biorąc pod uwagę plik

123
abc
@#$

to może produkować

nameFI4L1S-123
name5S8Shr-abc
namebRUjzV-@#$
Kusalananda
źródło
1

Bez użycia awk, po prostu proste bash

while read line; do
    printf "name%s-%s\n" \
        "$(tr -dc '[:alnum:]' </dev/urandom|head -c6)" \
        "$line"
done <myfile
Bogaty
źródło
1
Problem polega na tym, że możesz uszkodzić dane odczytane z pliku. Zobacz unix.stackexchange.com/questions/209123/…
Kusalananda
0
paste <(base64 -w6 /dev/urandom) input.txt | awk 'NF==2{print $1$2} NF!=2{exit}'

Wymagania - plik input.txt powinien zawierać tylko jedną kolumnę, innymi słowy, nie powinien mieć tabulatorów ani spacji, ponieważ były one używane jako domyślny separator poleceń awki paste(tylko znak tabulacji). W przeciwnym razie polecenie musi zostać nieco zmodyfikowane.

Uwaga: Base64 alfabet zawiera +i /znaków: stół Base64 , jeśli chcesz tylko cyfry i litery, można użyć base32polecenia - Base32 alfabetu .

Wejście

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

=== znaki dodane dla jasności.

Wynik

LYSdm8===my_line_a
5sSSNt===my_line_b
YVMdkA===my_line_c
3b/nsT===my_line_d
xt/AZO===my_line_e
MiniMax
źródło