Як я можу додати випадковий рядок для кожного рядка?


12

Я намагаюся додати випадковий рядок для кожного рядка під час запуску:

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

Перед цим генерується випадкова рядок:

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

Проблема полягає в тому, що він буде друкувати однаковий випадковий рядок для кожного рядка:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

Що мені робити, щоб отримати різні випадкові рядки для кожного рядка?


Замість деяких варіацій використання tr -dc '[:alnum:]' </dev/urandom | head -c 6було б простішим та обчислювально ефективнішим у використанні pwgen -s 6 1, а ще краще pwgen -s 6 $(wc -l myfile)- ви отримаєте саме всі випадкові рядки, які вам потрібні, за один кадр.
користувач1404316

Відповіді:


9

З функцією awk system() :

Зразок input.txt:

a
b
c

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

Вибірка зразка:

nameSDbQ7T-a
nameAliHY0-b
nameDUGP2S-c

system(command)
Виконайте команду операційної системи commandта поверніться до програми awk

https://www.gnu.org/software/gawk/manual/gawk.html#index-system_0028_0029-функція


Приємно, але чому я отримую tr: write error: Broken pipe?
user134969

@ user134969, це працює чудово. Переконайтеся, що ви не допустили жодних помилок у командному рядку
RomanPerekhrest

9

Ви не вважаєте, що це трохи очевидно? Ви просто генеруєте випадкову рядок один раз і зберігаєте її в ranзмінній та використовуєте її для всіх рядків!

Використання getlineв змінну з труби

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

При використанні command | getline varвихідна команда надсилається по трубі getline()в змінну і в неї var.

Також зверніть увагу, коли труба відкрита для виводу, awkзапам'ятовує пов'язану з нею команду, а наступні записи до команди додаються до попереднього запису. Нам потрібно зробити явний close()виклик команди, щоб не допустити цього.

Якщо вкладені одиничні лапки в str_generatorc викликають проблему, замініть його восьмеричним еквівалентом ( \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

8

Запуск одного примірника tr -dc '[:alnum:]' </dev/urandom | head -c 6на рядок введення буде контрпродуктивним, вам краще зробити:

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

Якщо вхідні дані не містять лапки , ні одиничні лапки, ви також можете використовувати m4«s mkstemp():

<input sed "s/.*/mkstemp(name)\`&'/" | m4

4

Ця зміна на пару інших відповідей робить генерацію випадкових рядків поза 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+ foldКонвеєр генерує нескінченний потік випадкових рядків з шести символів на стандартному вводі awk. awkбуде ігнорувати стандартне введення, якщо вказано ім'я файлу, тому ці випадкові рядки читаються getlineз /dev/stdinперемінної r. printfпотім використовується для префіксації рядків з файлу відповідним рядком.

З огляду на файл

123
abc
@#$

це може призвести

nameFI4L1S-123
name5S8Shr-abc
namebRUjzV-@#$

1

Без використання awk зовсім, просто просто bash

while read line; do
    printf "name%s-%s\n" \
        "$(tr -dc '[:alnum:]' </dev/urandom|head -c6)" \
        "$line"
done <myfile

1
Проблема з цим полягає в тому, що ви можете пошкодити дані, прочитані з файлу. Дивіться unix.stackexchange.com/questions/209123/…
Kusalananda

0
paste <(base64 -w6 /dev/urandom) input.txt | awk 'NF==2{print $1$2} NF!=2{exit}'

Вимоги - input.txt повинен містити лише один стовпець, інакше кажучи, він не повинен мати вкладок чи пробілів, оскільки вони використовуються як роздільник за замовчуванням за допомогою команд awkта paste(лише символу вкладки). В іншому випадку команду потрібно трохи змінити.

Примітка: Base64 алфавіт містить +і /символи: Base64 таблиці , якщо ви хочете тільки цифри і букви, ви можете використовувати base32команду - base32 алфавіт .

Вхідні дані

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

=== символів додано для наочності.

Вихідні дані

LYSdm8===my_line_a
5sSSNt===my_line_b
YVMdkA===my_line_c
3b/nsT===my_line_d
xt/AZO===my_line_e
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.