我想随机洗牌文本文件的行,并创建一个新文件。该文件可能有几千行。

我如何用cat, awk, cut等做到这一点?


当前回答

这是一个awk脚本

awk 'BEGIN{srand() }
{ lines[++d]=$0 }
END{
    while (1){
    if (e==d) {break}
        RANDOM = int(1 + rand() * d)
        if ( RANDOM in lines  ){
            print lines[RANDOM]
            delete lines[RANDOM]
            ++e
        }
    }
}' file

输出

$ cat file
1
2
3
4
5
6
7
8
9
10

$ ./shell.sh
7
5
10
9
6
8
2
1
3
4

其他回答

这个bash函数有最小的依赖关系(只有sort和bash):

shuf() {
while read -r x;do
    echo $RANDOM$'\x1f'$x
done | sort |
while IFS=$'\x1f' read -r x y;do
    echo $y
done
}

这是第一次尝试,对编码器来说很容易,但对CPU来说很难,它在每行前加上一个随机数,对它们进行排序,然后从每行中剥离随机数。实际上,这些行是随机排序的:

cat myfile | awk 'BEGIN{srand();}{print rand()"\t"$0}' | sort -k1 -n | cut -f2- > myfile.shuffled

另一种awk变体:

#!/usr/bin/awk -f
# usage:
# awk -f randomize_lines.awk lines.txt
# usage after "chmod +x randomize_lines.awk":
# randomize_lines.awk lines.txt

BEGIN {
  FS = "\n";
  srand();
}

{
  lines[ rand()] = $0;
}

END {
  for( k in lines ){
    print lines[k];
  }
}

如果你安装了Scala,这里有一行代码来洗牌输入:

ls -1 | scala -e 'for (l <- util.Random.shuffle(io.Source.stdin.getLines.toList)) println(l)'

尚未被提及:

unsort的util。语法(有点面向播放列表): unsort [-hvrpncmMsz0l][——help][——version][——random][——heuristic] [——identity][——filenames[=profile]][——separator sep][——concatenate] [——合并][——merge-random][——种子整数][——字符串作为][——零] [——linefeed][文件…] Msort可以逐行洗牌,但它通常是多余的: Seq 10 | msort -jq -b -l -n 1 -c r