我有一个带有换行符分隔字符串的文本文件。我的问题是按如下方式处理每一行:使用空格作为分隔符来打乱标记的顺序。
例如:
输入:
A B C
输出:
C A B
重复运行命令/脚本当然应该提供不同的顺序。
我当前的解决方案(对于单个文本行):
$ cat <file> | tr " " "\n" | shuf | tr "\n" " "
是否有一个很好的(更好的)命令行组合来处理具有多行的文本文件?
我有一个带有换行符分隔字符串的文本文件。我的问题是按如下方式处理每一行:使用空格作为分隔符来打乱标记的顺序。
例如:
输入:
A B C
输出:
C A B
重复运行命令/脚本当然应该提供不同的顺序。
我当前的解决方案(对于单个文本行):
$ cat <file> | tr " " "\n" | shuf | tr "\n" " "
是否有一个很好的(更好的)命令行组合来处理具有多行的文本文件?
POSIXly,您可以相对有效地执行此操作(肯定比为输入的每一行
awk
运行至少一个 GNU实用程序更有效):shuf
(请注意,在大多数
awk
实现中,在同一秒内运行相同的命令两次可能会给您相同的结果,因为使用的默认随机种子srand()
通常基于当前纪元时间(以秒为单位)。您的原始命令可以简化为
shuf -e A B C | tr "\n" " " && echo ""
或者
shuffled=( $(shuf -e A B C) ) ; echo ${shuffled[*]}
我认为这有点不那么hacky,并且从我的基本测试中也更快。
如果您有一个文件,
~/test
其中包含您可以使用以下命令随机播放和回显每一行
while IFS= read -r line; do shuffled=( $(shuf -e $line) ) ; echo ${shuffled[*]} ; done < ~/test
或以脚本形式:
您可能希望替换
~/test
为$1
将参数传递给脚本的位置。结果:
这是如何工作的:
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
我们的循环中输入行。给定
然后使用
shuffle
perl 的 List::Util 模块:使用 bash
read -a
和shuf
(但效率非常低,因为它每行运行 3 个实用程序,其中 2 个不是内置的):要将参数作为一行传递:
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>
虽然像@steeldriver 一样,我会使用适当的文本处理工具
perl
来完成这项工作zsh
,但我会提到外壳的一种hacky 方式:这有点骇人听闻。我们最终使用文件名生成,以便能够使用
o
glob 限定符,它允许我们实现任意排序顺序。在这里,我们正在使用 glob
/
(我们知道它始终存在),使用e
glob 限定符将其替换为我们数组的内容,然后基于n
xpression进行数值排序。o
REPLY=$RANDOM
e
这是使用“饱受诟病”的 c-shell 的一种方法:
这是一个更简单的。将您的字符串放入数组并用于
shuf
随机播放