打乱字符串中的单词

打乱字符串中的单词

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

例如:

输入: A B C

输出: C A B

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

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

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

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

答案1

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()通常基于当前纪元时间(以秒为单位))。

答案2

您的原始命令可以简化为

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

或者

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

我认为这不那么麻烦,而且从我的基本测试来看也更快。

如果您有一个文件~/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

给定

$ 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 -ashuf(但效率非常低,因为它每行运行 3 个实用程序,其中 2 个不是内置的):

$ while read -ra arr; do shuf -e -- "${arr[@]}" | paste -sd ' ' -; done < file
A C B
F E D
J I G H

答案4

要将参数作为一行传递:

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>

相关内容