用相同类型的随机字符替换最后一个字母数字

用相同类型的随机字符替换最后一个字母数字

我在文件中有一个简单的字母数字机器名称列表,我想更改最后一个字母或数字,但我希望它与字符类型匹配 - 因此,如果最后一个字符是数字,则应将其替换为随机数数字;如果最后一个字符是字母,则应替换为随机字母:

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

  1. 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
    
  2. 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

注意:这两种方法都不会检查随机选择的字符是否与前一个字符不同,但通常情况下是不同的。

相关内容