继自这个问题,我希望从文件中提取 10 行随机行,现在我希望将剩余的 90 行作为单独的文件。
由于文档有 100 行,索引从 1 到 100,因此问题归结为查找 的补集ind
,1, 2, ..., 100
其中
ind=$(shuf -i 1-100 -n 10 | sort -n)
所以我的问题是
- 如何
1, 2, ..., 100
有效地生成数组?和 - 看来这个可以用 来完成
comm
。如果是这样,我应该如何处理comm
数组(而不是文件)?
答案1
根据我在其他线程中的建议:
awk '
BEGIN { srand(); do a[int(100*rand()+1)]; while (length(a)<10) }
NR in a
' ~/orig.txt > ~/short.txt
可以将其更改为创建两个文件:
awk -v range=100 -v offset=1 -v amount=10 '
BEGIN { srand(); do a[int(range*rand()+offset)]; while (length(a)<amount) }
NR in a { print > "short.txt" }
!(NR in a) { print > "rest.txt" }
' ~/orig.txt
(请注意,在内部awk
不能使用~
。不过,可以使用HOME
through ENVIRON[]
,如:print > ENVIRON["HOME"] "/short.txt"
或 resp., print > ENVIRON["HOME"] "/rest.txt"
。)
答案2
好吧,转念一想——我工作过方式太难了。你只需要这个:
shuf -i 1-100 -n10 |
sed 's/$/{p;b\n}/' |
sed -nf - -e 'w separate_file' infile >outfile
尽管您可能需要一个文字换行符来代替替换n
中的sed
。无论如何,它的作用与下面相同 - 它只是不必费心执行所有其他 90 行 - 它们只是就位,因为它们在文件中 - 所以它们不需要任何特殊考虑。
这是整个交易:
set " $(shuf -i 1-100 -n 10) "
while [ "$((i+=1))" -le 100 ]
do [ -z "${1##*[!0-9]$i[!0-9]*}" ]
printf "$i%.$((!$?))s%.$?s\n" p H
done| sed -nf - -e '$!d;x;s/.//p' <infile >outfile
在那里 - 我们基本上只是编写一个sed
如下所示的脚本:
1H
2H
3H
4p
5H
...
90p
91H
...
依此类推,直到 100。在最后一行 - 在所有随机选择的行都已被p
打印之后,我们x
更改为H
旧空间,s///
替换掉第一个插入的\n
ewline 字符,并p
打印其余的部分。
要在没有 shell 循环的情况下执行此操作,您可以执行以下操作:
set "$(shuf -i 1-100 -n 10)"
{ seq 100 | grep -Fxv "$1"; echo "$1"; } |
sed '1,90s/$/H/;91,$s/$/p/' |
sed -nf - -e '$!d;x;s/.//p' <infile >outfile
但我不确定在这种规模上这是否会有好处。
不管怎样,我使用了一个seq 100
输出文件作为测试,并在运行它后打印出来......
3
4
5
19
57
63
64
73
80
88
1
2
6
7
8
9
10
11
12
13
14
15
16
...
...对于未包含在初始随机 100 中的所有行,一直到 100。
答案3
这是使用 bash 的另一种解决方案。首先,您可能希望从 ind 变量创建一个数组:
ind=($(shuf -i 1-100 -n 10 | sort -n))
要创建一个包含 1..100 范围内的数字的数组,一个简单的方法是:
numbers=({1..100})
为了获得补集,我将使用 uniq -u。该命令可以从已排序的列表中排序出所有重复项。最后的粘贴命令只是将所有值再次放入一行中。
complement=($(echo ${ind[*]} ${numbers[*]} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " - ))
echo ${complement[*]}
只是重新思考这个问题,所有这些也可以在没有 bash 数组的情况下完成:
ind=$(shuf -i 1-100 -n 10 | sort -n)
echo $ind {1..100} | sed 's/ /\n/g' | sort -n | uniq -u | paste -sd " " -
答案4
我相信您可以在命令行上完成所有操作,但有些问题使用实际的编程语言可以更好地解决。举个例子,基于 python 的问题解决方案是:
import random
import pprint
with open("file.txt", "w") as f:
# create a file filled with numbers from 00 to 99
f.writelines(map(lambda x: "%02d\n" % x, range(100)))
with open("file.txt") as f:
# read it and assign each line to array, strip newlines
ar = set(map(lambda x: x.strip(), f.readlines()))
selection = set(random.sample(ar, 10))
rest = ar - selection
pprint.pprint(selection)
pprint.pprint(rest)