在 Linux 環境下,編寫腳本(Python/AWK/Java 均可)從指定文件隨機讀取若干行,寫入目標文件。
隨機抽樣兩大流派:
#!/usr/bin/env python3
import sys, random
def random_lines(src, dst, k):
with open(src, 'r', encoding='utf-8') as f:
lines = f.readlines()
if k > len(lines): k = len(lines)
chosen = random.sample(lines, k)
with open(dst, 'w', encoding='utf-8') as f:
f.writelines(chosen)
if __name__ == '__main__':
# 用法: python3 random_lines.py source.txt target.txt 10
random_lines(sys.argv[1], sys.argv[2], int(sys.argv[3]))
# 抽取 10 行
awk 'BEGIN{srand()} {lines[NR]=$0} END{for(i=1;i<=10;i++) print lines[int(rand()*NR)+1]}' bigfile.txt > sample.txt
# 更標準的水庫抽樣 (GNU awk)
awk -v k=10 'BEGIN{srand()} NR<=k{a[NR]=$0; next} {j=int(rand()*NR); if(j sample.txt
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class RandomLineSampler {
public static void sample(String src, String dst, int k) throws IOException {
List reservoir = new ArrayList<>(k);
long count = 0;
try (BufferedReader br = Files.newBufferedReader(Paths.get(src))) {
String line;
while ((line = br.readLine()) != null) {
count++;
if (reservoir.size() < k) {
reservoir.add(line);
} else {
long r = new Random().nextLong(count);
if (r < k) reservoir.set((int) r, line);
}
}
}
Files.write(Paths.get(dst), reservoir, StandardCharsets.UTF_8);
}
public static void main(String[] args) throws IOException {
sample(args[0], args[1], Integer.parseInt(args[2]));
}
}
| 方案 | 內存 | 速度 | 適用文件大小 | 依賴 |
|---|---|---|---|---|
| Python 全量 | O(N) | 快 | < 500MB | Python 3 |
| AWK 水庫 | O(k) | 中 | 任意 (GB 級) | GNU Awk |
| Java 水庫 | O(k) | 中 | 任意 | JRE 8+ |
設置隨機種子:
random.seed(42)BEGIN{srand(42)}new Random(42L)小文件用 Python random.sample 一行搞定;大文件用 AWK/Java 水庫抽樣恆定內存。根據項目技術棧與文件體量選型即可。