除非您知道有多少行代表 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