次からこの問題、ファイルからランダムな10行を抽出したかったので、残りの90行を別々のファイルにしたいと思います。
ドキュメントには 1 から 100 までのインデックスがある 100 行があるので、問題は find の補数で帰結します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
これを変更して2つのファイルを作成できます。
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
に変更し、最初に挿入されたewline文字を置き換えて残りを印刷します。H
s///
\n
p
シェルループなしでこれを行うには、次のようにします。
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 を使います。このコマンドは、ソートされたリスト内のすべての重複項目をソートします。最後の貼り付けコマンドは、すべての値を1行に戻します。
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)