我有一个 40 000 行长的 CSV。从第 x 行读取到第 y 行的最简单工具是什么?
我确信有更专业的方法可以做到这一点,但我只想要一个以以下形式工作的 bash 脚本
readFile --from 10 --to 20
这样我就可以处理十行,然后再次调用它并再引入十行。我正在考虑只使用 AWK 脚本,但你能用cat
、grep
、tail
或 之类的东西更简单地做到这一点吗head
?
答案1
#!/bin/sh
while getopts "f:t:" option; do
case "$option" in
f) from=$OPTARG ;;
t) to=$OPTARG ;;
esac
done
if [ -z "$from" ] || [ -z "$to" ]; then
echo "must give both -f and -t" >&2
exit 1
fi
awk -v "from=$from" -v "to=$to" 'from <= NR && NR <= to' filename
# or:
sed -n "$from,$to p; $to q" filename
# or:
i=0
while read line; do
i=$(( i + 1 ))
if [ $i -ge $from ] && [ $i -le $to ]; then
printf "%s\n" "$line"
fi
[ $i -eq $to ] && break
done < filename
答案2
提取文件的第 10 到 20 行是head
和的简单组合tail
:
tail -n +11 | head -n 10 | mycommand
此命令会跳过 10 行并处理接下来的 10 行。如果您想按顺序处理文件中的所有行,但按 10 行为一组,有更好的方法。您可以head
重复阅读 10 行。请注意使用chunk=$(…; echo a)
后跟剥离a
, 来解决命令替换中最后换行符的抑制问题。这种方法的优点是即使输入是管道(无法倒带)也能工作,而且对于常规文件来说速度也更快。警告,未经测试的代码,直接在浏览器中键入。
while chunk=$(head -n 10; echo a); chunk=${chunk#a}; [ -n "$chunk" ]; do
printf %s "$chunk" | mycommand
done <filename
或者,您可以让 awk 完成这项工作。再次,未经测试。
awk '
{chunk = chunk $0 RS}
NR % 10 {print chunk | "mycommand"; close("mycommand"); chunk="" }
END {if (chunk != "") {print chunk | "mycommand"; close("mycommand"); chunk="" }}
' <filename