如何使用"while read line with tail -n"

5

问题:我有一个CSV转储文件,超过250,000行。当我使用while read时,需要一段时间(无意冒犯)。我想回到最后的10,000行来完成我需要做的事情,而不是250,000行。

代码片段:我的当前代码如下:

IFS=","
while read line
do

    awk_var=`echo "$line" | awk -F" " '{print $0}'`

    var_array=($awk_var)

    read -a var_array <<< "${awk_var}"

    echo "${var_array[1]}"


done </some_directory/directory/file_in_question.csv

问题:如何在使用bash脚本读取file_in_question.csv时,结合tail -n10000while read line命令使用?


"{print $0}"与awk中的"{print}"相同,这与根本不使用awk是相同的。你当时想做什么?这里的时间可能来自于对awk的250,000次调用(每个循环一次)。如果可以的话,请避免使用它们。 - Etan Reisner
@EtanReisner 首个参数是以秒为单位的Unix时间戳,因此我计算了一个边界(两个日期/时间戳),并提取了上述边界之间的数据。有什么替代方法可以使我的代码更快? - 3kstc
1
我的观点是,awk_var=$(echo "$line" | awk -F " " '{print $0}')awk_var=$(echo "$line")完全相同,与awk_var=$line完全相同,只是在第一种情况下使用$line可以减少两个外部命令、一个子shell和几行代码。此外,var_array=($awk_var)是错误的,并且您稍后会用read覆盖awk_var - Etan Reisner
3个回答

8

替换:

done </some_directory/directory/file_in_question.csv

使用:

done < <(tail -n10000 /some_directory/directory/file_in_question.csv)
<(tail -n10000 /some_directory/directory/file_in_question.csv | cut -d',' -f2)这个结构被称为进程替换,它创建了一个类似文件的对象,bash可以从中读取。因此,这将直接替换从some_directory/directory/file_in_question.csv读取的内容,改为从tail -n10000 /some_directory/directory/file_in_question.csv读取的内容。
像这样使用进程替换可以使您将while循环保留在主shell中,而不是子shell中。因此,在循环退出后,您在while循环中创建的变量将保留其值。

加速原始代码

如上所示的代码打印CSV文件的第二列。如果这是代码应该执行的全部内容,则可以替换为:
awk -F, '{print $2}' /some_directory/directory/file_in_question.csv

谢谢John,我有一个快速的问题 - 使用MyVar=$(some_command)(例如GetTodaysDate=$(date +%F))也被认为是进程替换吗? - 3kstc
@3kstc 不是,那是“命令替换”。不同之处在于“命令”替换捕获进程的stdout,而“进程”替换则创建一个类似文件的对象。 - John1024
哦,没错,抱歉 - 我把我的替换搞混了:S! - 3kstc
我该如何在这种情况下退出while read?编辑:算了,只需在循环内添加“break”命令即可。 - HereHere

2

类似于:

IFS=","
tail /var/log/httpd/error_log | while read foo bar
do
    echo $foo
done

我建议您在bash中使用read来分割文本,而不是在那里低效地调用awk。显然将整个脚本重写为awk脚本比使用shell更快,但awk是一种较难的、不太常见的语言。

0

或者这个。

while : 
do read l || { sleep 1 ; continue; }
   echo "==> $l"
done < /var/log/httpd/error_log

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接