如何获得一个shell脚本来正确地洗牌数组值?

如何获得一个shell脚本来正确地洗牌数组值?,shell,sed,Shell,Sed,我有一个非常棒的shell脚本,它工作得非常出色:获取一串Unicode值并将其洗牌。问题是,我需要绝对确保每个值都位于字符串中的不同位置 例如,如果我的字符串是(仅使用ascii): abcdefg 我需要知道洗牌后这些角色不会出现在同一位置: gbadcef不起作用,因为“d”在同一个位置。取最后一个值并将其放在第一位将有效 fabcde …但它没有给我应用程序所需的随机性 实际数据字符串是Unicode值、长、长、长分号分隔字符串: ₮„&a

我有一个非常棒的shell脚本,它工作得非常出色:获取一串Unicode值并将其洗牌。问题是,我需要绝对确保每个值都位于字符串中的不同位置

例如,如果我的字符串是(仅使用ascii):

abcdefg

我需要知道洗牌后这些角色不会出现在同一位置:

gbadcef不起作用,因为“d”在同一个位置。取最后一个值并将其放在第一位将有效

fabcde

…但它没有给我应用程序所需的随机性

实际数据字符串是Unicode值、长、长、长分号分隔字符串:

₮„‮″⃝Ⴎ𠂮ž etc.
以下是我目前拥有的洗牌代码:

#!/bin/bash
echo "Input Filename:";
read ifilename;
echo "Output Filename:";
read ofilename;
cat $ifilename | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n" > $ofilename;
这是一个伟大的,紧凑的,精彩的剧本,我认为来自StackOverflow社区的某个人。有人能告诉我如何修改它,以确保字符串中任何地方的字符都不会意外地出现在同一个位置吗


谢谢你的帮助

也许它没有用,因为我没有看到
perl
标记,但我会使用该工具来完成这项工作。该脚本使用两个参数,一个输入文件读取unicode字符串,一个输出文件写入无序字符串

script.pl的内容

use warnings;
use strict;
use List::Util qw( shuffle );

## Check arguments for two files, one for input and other for output.
die qq[Usage: perl $0 <input-file> <output-file>\n] unless @ARGV == 2;

## Open files.
open my $ifh, qq[<], shift @ARGV or die qq[Cannot open argument file\n];
open my $ofh, qq[>], shift @ARGV or die qq[Cannot open argument file\n];


## Read from input file ...
while ( <$ifh> ) { 

    ## Array with suffled characters.
    my @shuffle;

    ## Remove last newline character.
    chomp;

    ## Create an array with chars of input string.
    my @f = split /;/;

    ## Repeat: Shuffle array until no char keeps
    ## its original position.
    SHUFFLE: while ( 1 ) { 
        @shuffle = shuffle @f; 
        for my $i ( 0 .. $#f ) { 
            next SHUFFLE if $shuffle[ $i ] eq $f[ $i ];
        }   
        last;
    }   

    ## Print shuffled array.
    printf $ofh qq[%s\n], join qq[;], @shuffle;
}
使用正确的参数运行脚本:

perl script.pl infile outfile
执行后
outfile
的内容:

&#x020DD;&#x010AE;&#x02033;&#x0009E;&#x0201E;&#x020AE;&#x0202E;&#x200AE
&#x02099;&#x0ABCD;&#x02033;&#x020DD;&#x02043

也许它没有用,因为我没有看到
perl
标记,但我会使用该工具来完成这项工作。该脚本使用两个参数,一个输入文件读取unicode字符串,一个输出文件写入无序字符串

script.pl的内容

use warnings;
use strict;
use List::Util qw( shuffle );

## Check arguments for two files, one for input and other for output.
die qq[Usage: perl $0 <input-file> <output-file>\n] unless @ARGV == 2;

## Open files.
open my $ifh, qq[<], shift @ARGV or die qq[Cannot open argument file\n];
open my $ofh, qq[>], shift @ARGV or die qq[Cannot open argument file\n];


## Read from input file ...
while ( <$ifh> ) { 

    ## Array with suffled characters.
    my @shuffle;

    ## Remove last newline character.
    chomp;

    ## Create an array with chars of input string.
    my @f = split /;/;

    ## Repeat: Shuffle array until no char keeps
    ## its original position.
    SHUFFLE: while ( 1 ) { 
        @shuffle = shuffle @f; 
        for my $i ( 0 .. $#f ) { 
            next SHUFFLE if $shuffle[ $i ] eq $f[ $i ];
        }   
        last;
    }   

    ## Print shuffled array.
    printf $ofh qq[%s\n], join qq[;], @shuffle;
}
使用正确的参数运行脚本:

perl script.pl infile outfile
执行后
outfile
的内容:

&#x020DD;&#x010AE;&#x02033;&#x0009E;&#x0201E;&#x020AE;&#x0202E;&#x200AE
&#x02099;&#x0ABCD;&#x02033;&#x020DD;&#x02043

下面的Bash脚本随机洗牌字符列表,同时防止字符占据其先前的位置

#!/bin/bash
IFS=";"
while read -r -a array
do
    num=${#array[@]}
    for ((i = 0; i < num; i++))
    do
        r=$i
        while ((r == i)) || [[ ${new[r]} ]]
        do
            ((r = $RANDOM % num))
        done
        new[r]=${array[i]}
    done
    echo "Input:  ${array[*]}"
    echo "Output: ${new[*]}"
done
#/bin/bash
IFS=“;”
而read-r-a数组
做
num=${#数组[@]}
对于((i=0;i
例如:

$ charshuf < charfile
Input:  a;b;c;d;e;f;g;h;i;j;k;l
Output: j;h;i;a;b;k;f;e;g;c;l;d
Input:  1;2;3;4;5;6;7;8
Output: 6;3;8;2;4;7;5;1
$charshuf
以下Bash脚本随机洗牌字符列表,同时防止字符占据其先前位置

#!/bin/bash
IFS=";"
while read -r -a array
do
    num=${#array[@]}
    for ((i = 0; i < num; i++))
    do
        r=$i
        while ((r == i)) || [[ ${new[r]} ]]
        do
            ((r = $RANDOM % num))
        done
        new[r]=${array[i]}
    done
    echo "Input:  ${array[*]}"
    echo "Output: ${new[*]}"
done
#/bin/bash
IFS=“;”
而read-r-a数组
做
num=${#数组[@]}
对于((i=0;i
例如:

$ charshuf < charfile
Input:  a;b;c;d;e;f;g;h;i;j;k;l
Output: j;h;i;a;b;k;f;e;g;c;l;d
Input:  1;2;3;4;5;6;7;8
Output: 6;3;8;2;4;7;5;1
$charshuf
您需要什么样的随机性?你的限制使输出更少的随机性,而不是更多。只要它被“很好地洗牌”,它就不必像可能的那样随机。随机性不如知道在洗牌后每个字符都在不同的位置重要。你现有的脚本可以很容易地根据你的新需求进行修改。与其在所有字符之间添加空格并用换行符替换,不如用换行符替换每个与。洗牌后,删除空行,并在每行的开头添加一个符号和。您需要什么样的随机性?你的限制使输出更少的随机性,而不是更多。只要它被“很好地洗牌”,它就不必像可能的那样随机。随机性不如知道在洗牌后每个字符都在不同的位置重要。你现有的脚本可以很容易地根据你的新需求进行修改。与其在所有字符之间添加空格并用换行符替换,不如用换行符替换每个与。洗牌后,删除空行,并在每行的开头添加一个符号and。对于上述内容,是否可以对输入文件(将成为上述数据部分的.txt文件)进行类似的查询,然后写入用户指定的输出文件?我也不知道为什么要用“for”循环运行脚本——每个文件只需要运行两次(但我有数百个文件)。@user1149499:修改脚本以满足您的要求。好吧,我对perl不是很熟悉,但它不必是bash。对于上述内容,是否可以对输入文件(将成为上述数据部分的.txt文件)进行类似的查询,然后写入用户指定的输出文件?我也不知道为什么要用“for”循环运行脚本——每个文件只需要执行两次(但我有数百个文件)。@user1149499:修改脚本以满足您的要求。