[英]how can I let my shell script with 1 argument accept default unix commands in the command line
[英]How can I shuffle the lines of a text file on the Unix command line or in a shell script?
我想随机调整文本文件的行并创建一个新文件。 该文件可能有数千行。
我该如何使用cat
, awk
, cut
等方式呢?
Perl单线将是Maxim解决方案的简单版本
perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' < myfile
该答案通过以下方式补充了许多现有的出色答案:
现有的答案打包在灵活的shell函数中 :
stdin
输入,还接受文件名参数 141
安静地终止) 处理SIGPIPE
,而不是吵闹。 在将功能输出管道输送到较早关闭的管道(例如管道输送到head
时,这一点很重要。 进行性能比较 。
awk
, sort
和cut
POSIX兼容功能,改编自OP自己的答案 : shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print rand(), $0}' "$@" |
sort -k1,1n | cut -d ' ' -f2-; }
shuf() { perl -MList::Util=shuffle -e 'print shuffle(<>);' "$@"; }
shuf() { python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
' "$@"; }
有关此功能的Windows版本,请参见底部。
shuf() { ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
puts ARGF.readlines.shuffle' "$@"; }
性能比较:
注意:这些数字是在2012年末配备3.2 GHz Intel Core i5和运行OSX 10.10.3的Fusion Drive的iMac上获得的。 虽然时间会随所使用的OS,机器规格,所用的awk
实现而变化 (例如,OSX上使用的BSD awk
版本通常比GNU awk
慢,尤其是mawk
), 但这应该提供相对性能的一般含义 。
输入文件是一百万行文件 ,其中seq -f 'line %.0f' 1000000
产生。
时间以升序排列(最快的是第一个):
shuf
0.090s
0.289s
0.589s
1.342s
; 使用Python 3.4.2的2.407s
(!) awk
+ sort
+ cut
awk
3.003s
; 使用GNU awk
(4.1.1)的2.388s
; 1.811s
与mawk
(1.3.4); 为了进一步比较,上述未打包为功能的解决方案:
sort -R
(如果输入行重复,则不是真正的随机播放)
10.661s
分配更多的内存似乎没有什么不同 24.229s
bash
循环+ sort
32.593s
结论 :
shuf
,这是迄今为止最快的。 awk
+ sort
+ cut
组合 ; 您使用哪个awk
实现很重要( mawk
比GNU awk
快,BSD awk
最快)。 sort -R
, bash
循环和Scala。 Windows版本的Python解决方案 (Python代码相同,除了引号和与信号相关的语句的删除(Windows不支持)之外):
$OutputEncoding
): # Call as `shuf someFile.txt` or `Get-Content someFile.txt | shuf`
function shuf {
$Input | python -c @'
import sys, random, fileinput;
lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write(''.join(lines))
'@ $args
}
请注意,PowerShell可以通过其Get-Random
cmdlet在本地进行改组(尽管性能可能是个问题); 例如:
Get-Content someFile.txt | Get-Random -Count ([int]::MaxValue)
cmd.exe
(批处理文件): 保存到文件shuf.cmd
,例如:
@echo off
python -c "import sys, random, fileinput; lines=[line for line in fileinput.input()]; random.shuffle(lines); sys.stdout.write(''.join(lines))" %*
我使用一个很小的perl脚本,我称之为“ unsort”:
#!/usr/bin/perl
use List::Util 'shuffle';
@list = <STDIN>;
print shuffle(@list);
我也有一个以NULL分隔的版本,称为“ unsort0” ...方便与find -print0等一起使用。
PS:也投票赞成“ shuf”,我不知道这些天在coreutils中有没有……如果您的系统没有“ shuf”,以上内容可能仍然有用。
这是第一次尝试,在编码器上很容易,但在CPU上很难,它会在每行前添加一个随机数,对它们进行排序,然后从每行中剥离该随机数。 实际上,这些行是随机排序的:
cat myfile | awk 'BEGIN{srand();}{print rand()"\t"$0}' | sort -k1 -n | cut -f2- > myfile.shuffled
这是一个awk脚本
awk 'BEGIN{srand() }
{ lines[++d]=$0 }
END{
while (1){
if (e==d) {break}
RANDOM = int(1 + rand() * d)
if ( RANDOM in lines ){
print lines[RANDOM]
delete lines[RANDOM]
++e
}
}
}' file
输出
$ cat file
1
2
3
4
5
6
7
8
9
10
$ ./shell.sh
7
5
10
9
6
8
2
1
3
4
python的一线式:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
对于仅打印一条随机行:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
但是请参阅这篇文章 ,了解python random.shuffle()
的缺点。 它不适用于许多(超过2080个)元素。
简单的基于awk的函数将完成此任务:
shuffle() {
awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8-
}
用法:
any_command | shuffle
这在几乎所有的UNIX上都可以使用。 在Linux,Solaris和HP-UX上进行了测试。
更新:
请注意,前导零( %06d
)和rand()
乘法使其在sort
不理解数字的系统上也能正常工作。 可以按字典顺序对其进行排序(也称为正常字符串比较)。
Ruby FTW:
ls | ruby -e 'puts STDIN.readlines.shuffle'
一种基于scai的答案的 Python衬里,但是a)接受标准输入,b)使结果与种子可重复,c)仅挑选出所有行中的200条。
$ cat file | python -c "import random, sys;
random.seed(100); print ''.join(random.sample(sys.stdin.readlines(), 200))," \
> 200lines.txt
一种简单而直观的方法是使用shuf
。
例:
假设words.txt
为:
the
an
linux
ubuntu
life
good
breeze
要随机排列,请执行以下操作:
$ shuf words.txt
这将乱码的线投向标准输出 ; 因此,您必须将其通过管道传输到类似以下的输出文件 :
$ shuf words.txt > shuffled_words.txt
一种这样的随机运行可以产生:
breeze
the
linux
an
ubuntu
good
life
我们有一个软件包可以完成这项工作:
sudo apt-get install randomize-lines
例:
创建数字的有序列表,并将其保存到1000.txt:
seq 1000 > 1000.txt
随机播放,只需使用
rl 1000.txt
这是我作为rand.py保存在主文件夹中的python脚本:
#!/bin/python
import sys
import random
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
flist = f.readlines()
random.shuffle(flist)
for line in flist:
print line.strip()
在Mac OSX上, sort -R
和shuf
不可用,因此您可以在shuf
中将此别名为:
alias shuf='python rand.py'
如果像我一样,您是来这里寻找macOS的shuf
的替代品,然后使用randomize-lines
。
安装randomize-lines
(homebrew)软件包,该软件包具有rl
命令,其功能与shuf
相似。
brew install randomize-lines
Usage: rl [OPTION]... [FILE]...
Randomize the lines of a file (or stdin).
-c, --count=N select N lines from the file
-r, --reselect lines may be selected multiple times
-o, --output=FILE
send output to file
-d, --delimiter=DELIM
specify line delimiter (one character)
-0, --null set line delimiter to null character
(useful with find -print0)
-n, --line-number
print line number with output lines
-q, --quiet, --silent
do not output any errors or warnings
-h, --help display this help and exit
-V, --version output version information and exit
如果您安装了Scala,则可以使用以下方法来随机调整输入:
ls -1 | scala -e 'for (l <- util.Random.shuffle(io.Source.stdin.getLines.toList)) println(l)'
这个bash函数具有最小的依赖性(仅sort和bash):
shuf() {
while read -r x;do
echo $RANDOM$'\x1f'$x
done | sort |
while IFS=$'\x1f' read -r x y;do
echo $y
done
}
在Windows中,您可以尝试使用此批处理文件来帮助您重新整理data.txt,批处理代码的用法是
C:\> type list.txt | shuffle.bat > maclist_temp.txt
发出此命令后,maclist_temp.txt将包含随机的行列表。
希望这可以帮助。
截至目前尚未提及:
unsort
util。 语法(某种程度上面向播放列表):
unsort [-hvrpncmMsz0l] [--help] [--version] [--random] [--heuristic] [--identity] [--filenames[=profile]] [--separator sep] [--concatenate] [--merge] [--merge-random] [--seed integer] [--zero-terminated] [--null] [--linefeed] [file ...]
msort
可以按行随机播放,但这通常是过大的:
seq 10 | msort -jq -b -l -n 1 -cr
另一个awk
变体:
#!/usr/bin/awk -f
# usage:
# awk -f randomize_lines.awk lines.txt
# usage after "chmod +x randomize_lines.awk":
# randomize_lines.awk lines.txt
BEGIN {
FS = "\n";
srand();
}
{
lines[ rand()] = $0;
}
END {
for( k in lines ){
print lines[k];
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.