AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 539279
Accepted
Vladislavs Dovgalecs
Vladislavs Dovgalecs
Asked: 2019-09-06 15:37:15 +0800 CST2019-09-06 15:37:15 +0800 CST 2019-09-06 15:37:15 +0800 CST

随机播放字符串中的单词

  • 772

我有一个带有换行符分隔字符串的文本文件。我的问题是按如下方式处理每一行:使用空格作为分隔符来打乱标记的顺序。

例如:

输入: A B C

输出: C A B

重复运行命令/脚本当然应该提供不同的顺序。

我当前的解决方案(对于单个文本行):

$ cat <file> | tr " " "\n" | shuf | tr "\n" " "

是否有一个很好的(更好的)命令行组合来处理具有多行的文本文件?

linux text-processing
  • 7 7 个回答
  • 1872 Views

7 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2019-09-06T23:48:17+08:002019-09-06T23:48:17+08:00

    POSIXly,您可以相对有效地执行此操作(肯定比为输入的每一行awk运行至少一个 GNU实用程序更有效):shuf

    awk '
      BEGIN {srand()}
      {
        for (i = 1; i <= NF; i++) {
          r = int(rand() * NF) + 1
          x = $r; $r = $i; $i = x
        }
        print
      }' < your-file
    

    (请注意,在大多数awk实现中,在同一秒内运行相同的命令两次可能会给您相同的结果,因为使用的默认随机种子srand()通常基于当前纪元时间(以秒为单位)。

    • 6
  2. Zhenhir
    2019-09-06T16:14:20+08:002019-09-06T16:14:20+08:00

    您的原始命令可以简化为

    shuf -e A B C | tr "\n" " " && echo ""

    或者

    shuffled=( $(shuf -e A B C) ) ; echo ${shuffled[*]}

    我认为这有点不那么hacky,并且从我的基本测试中也更快。

    如果您有一个文件,~/test其中包含

    A B C
    D E F
    

    您可以使用以下命令随机播放和回显每一行

    while IFS= read -r line; do shuffled=( $(shuf -e $line) ) ; echo ${shuffled[*]} ; done < ~/test

    或以脚本形式:

    #!/bin/bash
    while IFS= read -r line
        do shuffled=( $(shuf -e $line) )
        echo ${shuffled[*]}
    done < ~/test
    

    您可能希望替换~/test为$1将参数传递给脚本的位置。

    结果:

    B C A
    G E F
    

    这是如何工作的:

    shuf -e在空格和换行符上拆分.. 但只是因为它将 ABC 视为三个参数。

    所以 shuf -e A B C 会洗牌 AB 和 C 但shuf -e "A B C" 不会洗牌 AB 和 C

    我们可以使用它来将每一行读入一个数组,然后再用echo.

    while IFS= read -r line;

    将每一行读入$line当它传递<给这个循环时。

    do shuffled=( $(shuf -e $line) )

    $shuffled通过从字面上扩展shuf -e $line为,从变量中的每一行创建一个数组shuf -e A B C。

    echo ${shuffled[*]}

    回显我们的数组,默认打印每个元素之间有空格

    < ~/test

    从~/test我们的循环中输入行。

    • 3
  3. steeldriver
    2019-09-06T16:24:39+08:002019-09-06T16:24:39+08:00

    给定

    $ cat file
    A B C
    D E F
    G H I J
    

    然后使用shuffleperl 的 List::Util 模块:

    $ perl -MList::Util=shuffle -alpe '$_ = join " ", shuffle @F' file
    C B A
    E D F
    I J G H
    

    使用 bashread -a和shuf(但效率非常低,因为它每行运行 3 个实用程序,其中 2 个不是内置的):

    $ while read -ra arr; do shuf -e -- "${arr[@]}" | paste -sd ' ' -; done < file
    A C B
    F E D
    J I G H
    
    • 3
  4. Quora Feans
    2019-09-06T16:15:01+08:002019-09-06T16:15:01+08:00

    要将参数作为一行传递:

    shuf -e one two three four是你需要的。

    shuf -e $(cat <file>) | tr "\n" " "对于一行文件,如您的示例中所示。

    对于多行:

    while read line; do shuf -e $line | tr "\n" " " && echo \n; done < <file>

    • 1
  5. Stéphane Chazelas
    2019-09-06T23:30:33+08:002019-09-06T23:30:33+08:00

    虽然像@steeldriver 一样,我会使用适当的文本处理工具perl来完成这项工作zsh,但我会提到外壳的一种hacky 方式:

    while read -rA words; do
      print -r -- /(e['reply=($words)']noe['REPLY=$RANDOM'])
    done < your-file
    

    这有点骇人听闻。我们最终使用文件名生成,以便能够使用oglob 限定符,它允许我们实现任意排序顺序。

    在这里,我们正在使用 glob /(我们知道它始终存在),使用eglob 限定符将其替换为我们数组的内容,然后基于nxpression进行数值排序。oREPLY=$RANDOM e

    • 1
  6. Rakesh Sharma
    2019-09-07T01:00:45+08:002019-09-07T01:00:45+08:00

    这是使用“饱受诟病”的 c-shell 的一种方法:

    % foreach line ( "`cat input.txt`" )
         set tokens = ( $line:x )
         foreach ran_idx ( `seq $#tokens | shuf` )
             printf '%s\n' ${tokens[$ran_idx]:q}
         end
    end
    
    • 0
  7. Teshan Shanuka J
    2021-03-19T22:15:20+08:002021-03-19T22:15:20+08:00

    这是一个更简单的。将您的字符串放入数组并用于shuf随机播放

    SA=($"A B C")
    shuf -e ${SA[@]}
    
    • 0

相关问题

  • 在awk中的两行之间减去相同的列

  • 多行文件洗牌

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

  • 如何更改字符大小写(从小到大,反之亦然)?同时[重复]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve