![用相同类型的随机字符替换最后一个字母数字](https://linux22.com/image/152878/%E7%94%A8%E7%9B%B8%E5%90%8C%E7%B1%BB%E5%9E%8B%E7%9A%84%E9%9A%8F%E6%9C%BA%E5%AD%97%E7%AC%A6%E6%9B%BF%E6%8D%A2%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AF%8D%E6%95%B0%E5%AD%97.png)
我在文件中有一个简单的字母数字机器名称列表,我想更改最后一个字母或数字,但我希望它与字符类型匹配 - 因此,如果最后一个字符是数字,则应将其替换为随机数数字;如果最后一个字符是字母,则应替换为随机字母:
bob1234
pittsburgh
0091919
会成为:
bob1239
pittsburgp
0091915
答案1
尝试:
awk '
BEGIN{
srand()
letter = "abcdefghijklmnopqrstuvwxyz"
digit = "0123456789"
}
function find_in(set) {
if (index(set, c)) {
c = substr(set, int(rand() * length(set) + 1), 1)
return 1
}
}
$0 != "" {
c = substr($0, length)
if (find_in(letter) || find_in(digit)) sub(/.$/, c)
}
{print}'
请注意,对于大多数awk
实现,如果您在同一秒内运行这些命令两次,您将得到相同的结果,因为伪随机生成器的种子基于当前时间(以秒为单位)。
替换字符是随机的,这意味着它可能与原始字符相同。如果您想从可能的替换列表中排除原始版本,您可以将该find_in
函数更改为:
function find_in(set, n) {
if (n = index(set, c)) {
set = substr(set, 1, n - 1) substr(set, n + 1)
c = substr(set, int(rand() * length(set) + 1), 1)
return 1
}
}
答案2
使用perl字符串::随机模块:
perl -MString::Random -pe '
BEGIN{$s = String::Random->new}
s{[a-z0-9]$}{$s->randpattern($& =~ /\d/ ? "n" : "c")}e
' file
请注意,这并不排除替换字符与原始字符相同。解决这个问题的一种可能低效且丑陋的方法可能是“掷骰子”,直到生成不同的角色:
perl -MString::Random -pe '
BEGIN{$s = String::Random->new}
s{[a-z0-9]$}{do {$c = $s->randpattern($& =~ /\d/ ? "n" : "c")} until $c ne $&; $c}e
' file
答案3
纯
bash
法:printf -v s '%s' {a..z} {A..Z} {0..9} while read x; do n=${x:((-1))} echo -n ${x%?} p=${s#*$n} echo ${s:(( (${#p}>=10) ? RANDOM*52/32768 : 52 + RANDOM*10/32768 )):1} done < file
GNU
sed
方法,使用e
估价运行tr
命令head
/dev/urandom生成随机字符:sed 's/\(.*\)\(.\)$/\ printf \1 ; \ echo \2 | \ tr '[:alpha:][:digit:]' "$({ tr -dc '[:alpha:]' | head -c 52; \ tr -dc '[:digit:]' | head -c 10; \ } < \/dev\/urandom;)"/e' file
输出(运行之间有所不同):
bob1237
pittsburgq
0091916
注意:这两种方法都不会检查随机选择的字符是否与前一个字符不同,但通常情况下是不同的。