Как я могу добавить случайную строку для каждой строки?

12

Я пытаюсь добавить случайную строку для каждой строки во время работы:

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

Перед этим генерируется случайная строка:

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

Проблема в том, что он напечатает одну и ту же случайную строку для каждой строки:

nameGQz3Ek-
nameGQz3Ek-
nameGQz3Ek-

Что я должен сделать, чтобы получить разные случайные строки для каждой строки?

user134969
источник
Вместо некоторой вариации tr -dc '[:alnum:]' </dev/urandom | head -c 6, он будет проще и вычислительнее эффективнее в использовании pwgen -s 6 1, а еще лучше pwgen -s 6 $(wc -l myfile), даст вам все нужные вам случайные строки за один выстрел.
user1404316

Ответы:

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-function

RomanPerekhrest
источник
Хорошо, но почему я получаю 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_generatorявляются причиной проблемы, замените ее восьмеричным эквивалентом ( \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
источник
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}'

Если ваш ввод не содержит обратных кавычек или одинарных кавычек, вы также можете использовать m4s 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/…
Кусалананда
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
MiniMax
источник