如何编写脚本保留$1-$9列并随机打乱文件$10-$17列内容
实现每行前9列保留、后8列随机重排的脚本方案
嘿,这个需求我熟!要搞定把每行前9列原样保留,同时把所有行的后8列(也就是每行第10到17列的内容)作为整体随机打乱,再重新拼回对应的前9列后面,这里有两个实用的方案,你可以根据自己的环境选择:
方案一:用awk + shuf快速实现(适合Linux环境)
这个方法利用shuf命令的随机打乱能力,搭配awk提取列,操作简单直接:
# 第一步:提取所有行的后8列,随机打乱后存到临时文件 awk '{print $10, $11, $12, $13, $14, $15, $16, $17}' input.txt | shuf > temp_shuffled.txt # 第二步:把原文件的前9列和打乱后的后8列逐行合并 paste <(awk '{print $1, $2, $3, $4, $5, $6, $7, $8, $9}' input.txt) temp_shuffled.txt > output.txt # 清理临时文件 rm temp_shuffled.txt
步骤解释:
- 第一行用awk提取每行的第10到17列,通过
shuf命令随机打乱这些行,结果存到临时文件temp_shuffled.txt - 第二行用
paste命令,把原文件的前9列(同样用awk提取)和打乱后的后8列逐行拼接,输出到最终的output.txt - 最后删掉临时文件,保持工作目录整洁
注意:如果是在macOS上,shuf命令默认没有,需要先通过Homebrew安装coreutils(brew install coreutils),然后用gshuf代替上面的shuf。
方案二:纯awk脚本(无需临时文件,跨平台)
如果你不想用临时文件,或者需要跨平台运行,这个纯awk的方案更合适,它用Fisher-Yates洗牌算法来随机打乱后8列的数组:
创建一个名为shuffle_suffix.awk的文件,内容如下:
BEGIN { # 读取输入文件的每一行,拆分前9列和后8列到数组 while ((getline line < ARGV[1]) > 0) { split(line, cols) # 拼接前9列并保存 prefix[++count] = cols[1] " " cols[2] " " cols[3] " " cols[4] " " cols[5] " " cols[6] " " cols[7] " " cols[8] " " cols[9] # 拼接后8列并保存 suffix[count] = cols[10] " " cols[11] " " cols[12] " " cols[13] " " cols[14] " " cols[15] " " cols[16] " " cols[17] } close(ARGV[1]) # 用Fisher-Yates算法随机打乱suffix数组 srand() for (i = count; i > 1; i--) { j = int(rand() * i) + 1 # 交换两个元素 temp = suffix[i] suffix[i] = suffix[j] suffix[j] = temp } # 输出合并后的每行内容 for (i = 1; i <= count; i++) { print prefix[i], suffix[i] } }
运行方法:
awk -f shuffle_suffix.awk input.txt > output.txt
步骤解释:
- 脚本先读取输入文件的所有行,把每行的前9列和后8列分别存入
prefix和suffix两个数组 - 然后用Fisher-Yates洗牌算法对
suffix数组进行随机打乱,这个算法能保证每个元素的随机位置是公平的 - 最后把每个前9列条目和打乱后的对应后8列条目拼接,输出到结果文件
额外提示
- 确保你的输入文件每行都有17列,如果存在列数不一致的行,脚本可能会出错,建议先检查输入文件的格式
- 如果需要处理超大文件,方案二的纯awk脚本内存占用会更低,因为它不需要额外的临时文件存储
内容的提问来源于stack exchange,提问作者rishi
相关产品推荐
相关产品推荐

