我需要为记录唯一地打上UUID标记(用于关联ID)。我无法看到直接通过选项完成此操作的方法,这种操作是否可能?如果不可能,是否有一些解决方法可以实现此目的?
在jq中生成随机数或字符串是否可能?
--argjson initialRandomNumber
),在jq
中可以生成伪随机数,使用$RANDOM$RANDOM
代替$RANDOM
旨在增加初始伪随机值的范围。我使用了 Rosettacode jq: random numbers 中 nextRandomNumber
函数的略微修改版本,如下代码所示,用于生成随机数字、字符串和 UUID。每个函数都接受一个参数 $state
并在响应中提供一个新状态 newState
以供后续调用。因为您询问如何生成:1. 随机数,2. 随机字符串,3. UUID,因此您可以在我的代码中找到 6 个函数来生成单个实例和数组。您可以选择需要的函数并将其用作jq
过滤器。#!/bin/bash
jq -c -r -n --argjson initialRandomNumber "$RANDOM$RANDOM" '
# 15-bit integers generated using the same formula as rand() from the Microsoft C Runtime.
# The random numbers are in [0 -- 32767] inclusive.
#
# Input:
# first call: $state = a random number provided to jq by parameter
# subsequent call: $state = "newState" from last response
#
# Output:
# object with pseudo-random number and "newState" for a subsequent call.
def nextRandomNumber($state):
( (214013 * $state) + 2531011) % 2147483648 # mod 2^31
| { newState: .,
randomNumber: (. / 65536 | floor) };
def nextRandomNumbers($state; $count):
[foreach range($count) as $x (nextRandomNumber($state); nextRandomNumber(.newState); .)]
| { newState: .[-1].newState,
randomNumbers: map(.randomNumber) };
# ----- random UUID ---------------
def hexByte:
[. / 256 % 16, . % 16]
| map(if . < 10 then . + 48 else . + 87 end) # ASCII: 0...9: 48-57, a...f: 97-102
| implode;
def nextRandomUUID($state):
nextRandomNumbers($state; 16)
| .newState as $newState
| .randomNumbers
| map(hexByte)
| "\(.[0:4] | join(""))-\(.[4:6] | join(""))-\(.[6:8] | join(""))-\(.[8:10] | join(""))-\(.[10:] | join(""))"
| { newState: $newState,
randomUUID: . };
def nextRandomUUIDs($state; $count):
[foreach range($count) as $x (nextRandomUUID($state); nextRandomUUID(.newState); .)]
| { newState: .[-1].newState,
randomUUIDs: map(.randomUUID) };
# ----- random String ---------------
def letter:
. % 52
| [if . < 26 then . + 65 else . + 71 end] # ASCII: A...Z: 65-90, a...z: 97-122
| implode;
def nextRandomString($state; $minLength; $maxLength):
nextRandomNumber($state)
| (try (.randomNumber % ($maxLength - $minLength + 1) + $minLength) catch $minLength) as $length
| nextRandomNumbers(.newState; $length)
| .newState as $newState
| .randomNumbers
| map(letter)
| join("")
| { newState: $newState,
randomString: . };
def nextRandomStrings($state; $count; $minLength; $maxLength):
[foreach range($count) as $x (nextRandomString($state; $minLength; $maxLength); nextRandomString(.newState; $minLength; $maxLength); .)]
| { newState: .[-1].newState,
randomStrings: map(.randomString) };
# ----- example usage ---------------
nextRandomNumber($initialRandomNumber) # see output 1
# nextRandomNumbers($initialRandomNumber; 3) # see output 2
# nextRandomUUID($initialRandomNumber) # see output 3
# nextRandomUUIDs($initialRandomNumber; 3) # see output 4
# nextRandomString($initialRandomNumber; 10; 15) # see output 5
# nextRandomStrings($initialRandomNumber; 3; 6; 10) # see output 6
# nextRandomNumber($initialRandomNumber) | nextRandomNumbers(.newState; 3) # see output 7
'
输出 1
: 生成伪随机数
{"newState":912028498,"randomNumber":13916}
输出2
:生成3个伪随机数
{"newState":677282016,"randomNumbers":[10202,20943,6980]}`
输出 3
: 生成随机 UUID
{"newState":1188119770,"randomUUID":"cdcda95b-af57-1303-da72-d21c6e7b1861"}
输出 4
:生成 3 个随机 UUID
{"newState":907540185,"randomUUIDs":["855c1445-b529-4301-a535-20cb298feaff","5b685e49-8596-830e-f56a-0a22c43c4c32","35fed6d8-d72b-2833-fd6f-f99154358067"]}
输出 5
: 生成长度为10-15的随机字符串
{"newState":1037126684,"randomString":"SJadqPGkERAu"}`
输出 6
: 随机生成3个长度在6-10之间的字符串。
{"newState":316121190,"randomStrings":["eNKxechu","XPkvNg","TIABHbYCxB"]}`
输出 7
: 使用newState
来生成第二次调用生成 3 个随机数
{"newState":808494511,"randomNumbers":[26045,16811,12336]}`
目前 jq 不支持 UUID 生成,因此最好的方法是将 UUID 输入 jq,例如:
ruby -e 'require "securerandom"; p SecureRandom.uuid' | jq '{uuid: .}'
{
"uuid": "5657dd65-a495-4487-9887-c7f0e01645c9"
}
https://rosettacode.org/wiki/Linear_congruential_generator#jq
假设有一个uuid生成器,比如uuidgen,您可以使用以下方式之一的input
或inputs
:
jq -nR '[range(0;10) | input]' < <(while true; do uuidgen ; done)
(注意这里避免了使用操作系统的管道。)