ฉันจะเพิ่มสตริงแบบสุ่มสำหรับแต่ละบรรทัดได้อย่างไร


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)จะให้สตริงสุ่มทั้งหมดที่คุณต้องการในนัดเดียว
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


ดี แต่ทำไมฉันได้รับ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

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}'

หากใส่ของคุณไม่ได้มี backticks มิได้ราคาเดียวคุณยังสามารถใช้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 จะไม่สนใจเข้ามาตรฐานถ้าชื่อไฟล์ที่มีให้เพื่อสตริงสุ่มเหล่านี้จะถูกอ่านโดยจากการเข้าไปในตัวแปร จะใช้เพื่อนำหน้าบรรทัดจากไฟล์ด้วยสตริงที่เหมาะสมawkawkgetline/dev/stdinrprintf

รับไฟล์

123
abc
@#$

สิ่งนี้อาจผลิต

nameFI4L1S-123
name5S8Shr-abc
namebRUjzV-@#$


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.