我尝试随机显示25%的文件行
这是我的剧本:
file=$1
nb_lignes=$(wc -l $file | cut -d " " -f1)
num_lines_to_get=$((25*${nb_lignes}/100))
for (( i=0; i < $num_lines_to_get; i++))
do
line=$(head -$((${RANDOM} % $nb_lignes)) $file | tail -1)
echo "$line"
done
fi
我像那样跑
./script.sh file
文件是:
xxxxxxxx-54.yyyyy
xxxxxxxx-55.yyyyy
xxxxxxxx-60.yyyyy
xxxxxxxx-66.yyyyy
我的问题请问我怎么能消除54 55,我的意思是我喜欢这个列表的25%而不是这两行54和55,我想在命令中指定它
./script.sh file 54 55
谢谢。
答案 0 :(得分:4)
除非您知道有多少行代表100%,否则无法计算25%,因此您的所有解决方案将(1)单通并将您的文件存储在内存中,或(2)按顺序多次通过收集行数。我不知道你要处理的文件有多长,但我还是更喜欢第二个选项,所以这就是我的答案。
如果您正在运行Linux,那么您可能拥有大多数工具的GNU版本。一种解决方案可能是:
#!/bin/sh
linecount=$(awk 'END{printf("%d", NR * 0.25)}' input.txt)
exclude="$@"
egrep -vw "${exclude// /|}" input.txt | shuf -n$linecount
或者:
#!/bin/sh
linecount=$(awk 'END{printf("%d", NR * 0.25)}' input.txt)
exclude="$@"
egrep -vw "${exclude// /|}" input.txt | sort -R | head -n $linecount
此解决方案假定“xxxxxx”和“yyyyy”字符串不包含您尝试跳过的数字的字分隔版本。如果他们可能,那么你应该给我们更多的细节,比如实际的样本数据。
如果您使用的是FreeBSD或OSX,那么sort
没有-R
选项,并且不包含shuf
,但您仍然可以完成此操作。您的系统中将有一个名为jot
的工具。它可用于生成范围内的随机数。所以这有点尴尬,但它确实有效:
#!/bin/sh
# `awk` is a little heaver than `wc`, but you don't need to parse its output.
lines=$(awk 'END{printf("%d", NR * 0.25)}' input.txt)
exclude="$@"
# First, put a random number at the beginning of each line.
while read line; do
# skip lines that match our exclusion list
if [[ $line =~ -($exclude). ]]; then
continue
fi
echo "`jot -r 1 1 10000000` $line"
done < input.txt > stage1.txt
# Next, sort by the random number.
sort -n stage1.txt > stage2.txt
# Last, remove the number from the start of each line.
sed -r 's/^[0-9]+ //' stage2.txt > stage3.txt
# Show our output
head -n $lines stage3.txt
# Clean up
rm stage1.txt stage2.txt stage3.txt
如果您愿意,可以将这些行中的一些组合在一起,以避免将事物分级为单独的文件。
#!/bin/sh
lines=$(awk 'END{printf("%d", NR * 0.25)}' input.txt)
exclude="$@"
while read line; do
if [[ $line =~ -(${exclude// /|})\. ]]; then
continue
fi
echo "`jot -r 1 1 10000000` $line"
done < input.txt | sort -n | sed -r 's/^[0-9]+ //' | head -n $lines
# no clean-up required
答案 1 :(得分:2)
您可以使用一系列unix工具。 shuf
是一个很好的wc
和awk
。使用相同的方法计算线条,但随后调整要打印的行数以忽略某些线条,然后打印随机数量的线条。
num_lines=$(wc -l $file | cut -f1 -d' ' )
high=55
low=54
if [ "$num_lines" -ge $high ]; then : $((num_lines--)); fi
if [ "$num_lines" -ge $low ]; then : $((num_lines--)); fi
awk '(NR != '$low' && NR != '$high') { print }' < $file \
| shuf -n $((num_lines / 4))
请注意,if语句的顺序很重要,因此会发生正确的减法次数(即如果文件有54行,则只应跳过一行,因此只有一行减法,如果有55行,然后将跳过两行,并且这种排序是必需的,否则第二次减法将不会发生。)
注意,如果您希望这些行按其原始顺序排列,则可以使用以下代码来代替最后一个awk .. | shuf ..
管道。
awk '(NR != '$low' && NR != '$high') { print NR,$0 }' < $file \
| shuf -n $((num_lines / 4)) | sort -n | cut -f2- -d' '
(它首先用它的行号标记每一行,然后按此排序,然后将其删除,即Schwartzian Transform。)