返回

使用Python随机排列输入行

Linux

使用 Python 随机排列输入行

问题

我们希望编写一个 Python 脚本来随机排列给定的输入行。具体地说,我们希望能够:

  • 以指定的文件或标准输入作为输入
  • 根据需要重复输出行
  • 限制输出行的数量
  • 将行分隔符指定为换行符或空终止符

解决方法

为了解决这个问题,我们可以使用 Python 的 randomsys 模块。核心思想是将输入行存储在列表中,然后使用 random.shuffle() 函数随机排列它们。根据提供的参数,我们可以输出指定数量的行,并根据需要重复输出它们。

为了实现此功能,我们可以编写一个名为 shuf_lines() 的函数,它接受以下参数:

  • lines:输入行的列表
  • repeat:一个布尔值,指示是否重复输出行
  • head_count:要输出的最大行数
  • zero_terminated:一个布尔值,指示行分隔符是换行符还是空终止符
import random
import sys

def shuf_lines(lines, repeat, head_count, zero_terminated):
    delimiter = '\0' if zero_terminated else '\n'
    if repeat and not head_count:
        while True:
            print(random.choice(lines), end=delimiter)
    else:
        random.shuffle(lines)
        count = min(head_count, len(lines)) if head_count else len(lines)
        for i in range(count):
            print(lines[i], end=delimiter)

然后,我们可以编写一个 main() 函数来解析命令行参数并调用 shuf_lines() 函数。

def main():
    parser = argparse.ArgumentParser(
        prog='shuf',
        description='Write a random permutation of the input lines to standard output.',
        add_help=False
    )

    parser.add_argument('-e', '--echo', action='store_true',
                        help='treat each ARG as an input line')
    parser.add_argument('-i', '--input-range',
                        metavar='LO-HI', help='treat each number LO through HI as an input line')
    parser.add_argument('-n', '--head-count', type=int,
                        help='output at most COUNT lines')
    parser.add_argument('-r', '--repeat', action='store_true',
                        help='output lines can be repeated')
    parser.add_argument('-z', '--zero-terminated', action='store_true',
                        help='line delimiter is NUL, not newline')
    parser.add_argument('--help', action='help',
                        help='display this help and exit')
    parser.add_argument('files', metavar='SOURCE', nargs = '*',
                        help='input file name or - for standard input')

    args = parser.parse_args()

    # ... (略)

一个关键技巧

请注意,我们使用 args.files or args.files == [] 来确保即使参数列表为空,代码块也能运行。这是因为 shuf 命令接受一个可选的文件列表作为输入。如果未指定文件,则默认使用标准输入。通过使用 or args.files == [],我们可以涵盖这种情况,并始终读取输入。

结论

使用 shuf_lines() 函数和 main() 函数,我们现在可以轻松地随机排列输入行,并控制输出行为。这对于创建随机抽样、洗牌数据集或生成随机文本很有用。

常见问题解答

Q1:我可以使用空终止符来分隔行吗?

A1:是的,使用 -z 标志,你可以将行分隔符指定为空终止符。

Q2:我可以指定要输出的行数吗?

A2:是的,使用 -n 标志,你可以指定要输出的最大行数。

Q3:我可以重复输出行吗?

A3:是的,使用 -r 标志,你可以启用行重复。

Q4:我可以从特定范围内生成数字行吗?

A4:是的,使用 -i LO-HI 标志,你可以从 LO 到 HI 的范围内生成数字行。

Q5:如何使用标准输入作为输入?

A5:只需在命令行中不指定任何文件即可。例如:shuf | sort