Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash Shell脚本(在循环中运行sed)未完成大文件_Bash_Shell - Fatal编程技术网

Bash Shell脚本(在循环中运行sed)未完成大文件

Bash Shell脚本(在循环中运行sed)未完成大文件,bash,shell,Bash,Shell,下面是我将转换后的数据转换成新文件的代码 cat Report.csv > /tmp/report.part while read line do comp1=$(echo $line | awk -F, '{print $1}') timestamp=$(echo $line | awk -F, '{print $1}') converted=$(ssboetod "$timestamp") sed -i "s/$timestamp/$converted/g" Report.csv d

下面是我将转换后的数据转换成新文件的代码

cat Report.csv > /tmp/report.part

while read line
do
comp1=$(echo $line | awk -F, '{print $1}')
timestamp=$(echo $line | awk -F, '{print $1}')
converted=$(ssboetod "$timestamp")
sed -i "s/$timestamp/$converted/g" Report.csv
done < /tmp/report.part
预期产出为:

Fri Feb 20 11:31:49 2015,ABC
Fri Feb 20 10:12:32 2015,XYZ 
Fri Feb 20 14:58:53 2015,DEF 

看看上面的代码和文件,我想我们清楚需要什么。我只想把长格式的日期转换成日期格式。代码运行良好。如果我有少量的行,那么根本就没有问题。我目前正在处理一个有150000条记录的大文件。代码被卡住了,根本不退出。任何人都可以帮我解决我在这里遗漏的问题。

您可以用一种稍微简单(且更快)的方法来处理,只需修改一次文件,但使用多个
sed
替换:

#! /bin/bash
infile='Report.csv'

while read line
do
    timestamp=$(echo "$line" | awk -F, '{print $1}')
    converted=$(ssboetod "$timestamp")
    script="s/$timestamp/$converted/g; $script"
done < "$infile"

cp "$infile" .backup.csv
sed -i -e "$script" "$infile"

这就足够了(可能是条形时区)。

您可以用一种稍微简单一点(也快得多)的方法来处理它,只需修改一次文件,但使用多个
sed
替换:

#! /bin/bash
infile='Report.csv'

while read line
do
    timestamp=$(echo "$line" | awk -F, '{print $1}')
    converted=$(ssboetod "$timestamp")
    script="s/$timestamp/$converted/g; $script"
done < "$infile"

cp "$infile" .backup.csv
sed -i -e "$script" "$infile"

这看起来很像,但是如果我们假设报告包含多个时间戳,并且您想要转换所有时间戳,那么可以尝试

cut -d, -f1 Report.csv |
sort -u |
while read timestamp; do
    converted=$(ssboetod "$timestamp")
    echo "s/$timestamp/$converted/"
done |
sed -i -f - Report.csv
。。。假设您的
sed
可以容忍
-f-
从标准输入读取脚本(并非所有变体都可以这样做,但Linux应该可以)


通过从开始到结束只打开、读取和回写一次
Report.csv
(再加上另一次通读以读取时间戳),这应该比脚本快得多,脚本会为文件中的每一行重写整个文件一次,有时是不必要的。

这看起来很像,但如果我们假设报告包含多个时间戳,并且您希望转换所有时间戳,那么可以尝试

cut -d, -f1 Report.csv |
sort -u |
while read timestamp; do
    converted=$(ssboetod "$timestamp")
    echo "s/$timestamp/$converted/"
done |
sed -i -f - Report.csv
。。。假设您的
sed
可以容忍
-f-
从标准输入读取脚本(并非所有变体都可以这样做,但Linux应该可以)

通过从开始到结束只打开、读取和回写一次
Report.csv
(再加上另一次通读以读取时间戳),这应该比脚本快得多,脚本会为文件中的每一行重写整个文件一次,有时是不必要的。

感谢您的帮助:)

我按照tripleee的建议更改了我的while循环。下面给出的是代码,它工作得非常好,延迟也在几秒钟内

cut -d, -f1 Report.csv |
sort -u |
while read timestamp; do
    converted=$(ssboetod "$timestamp")
    echo "s/$timestamp/$converted/"
done |
sed -i -f - Report.csv
谢谢你的帮助:)

我按照tripleee的建议更改了我的while循环。下面给出的是代码,它工作得非常好,延迟也在几秒钟内

cut -d, -f1 Report.csv |
sort -u |
while read timestamp; do
    converted=$(ssboetod "$timestamp")
    echo "s/$timestamp/$converted/"
done |
sed -i -f - Report.csv


我想,
$comp1
是多余的。除此之外,其余的看起来不错。它可能是
ssboetod
不工作吗?当数据是10行时,它就工作了。如果它那么长,可能执行命令需要很长时间。试着在每次迭代中打印一些东西,看看它是否很慢。这样你就能知道是速度还是其他原因。还有,什么是
ssboetod
?如果它是一个需要时间的外部命令,这可能是问题所在。@程序员,也许可以尝试使用我所做的,例如类似于
$(date+'%a%m%d%H:%m:%S%Y'-d@$timestamp)
直接,而不是
ssboetod
的说法,顺便说一句,代码被“卡住”是完全错误的。如果您给它足够的时间/天/年运行,它将退出。如果您使用
bash-xyourscript
运行脚本,或者添加echo命令以登录到stderr,您会看到它正在运行,而不是真正卡住。我想
$comp1
是多余的。除此之外,其余的看起来不错。它可能是
ssboetod
不工作吗?当数据是10行时,它就工作了。如果它那么长,可能执行命令需要很长时间。试着在每次迭代中打印一些东西,看看它是否很慢。这样你就能知道是速度还是其他原因。还有,什么是
ssboetod
?如果它是一个需要时间的外部命令,这可能是问题所在。@程序员,也许可以尝试使用我所做的,例如类似于
$(date+'%a%m%d%H:%m:%S%Y'-d@$timestamp)
直接,而不是
ssboetod
的说法,顺便说一句,代码被“卡住”是完全错误的。如果您给它足够的时间/天/年运行,它将退出。如果您使用
bash-x yourscript
运行脚本,或者添加echo命令以登录到stderr,您会看到它正在做一些事情,而不是真正卡住。事实上,要获得
时间戳
,在IFS=“,”读取时间戳rest时只说
,速度会更快,然后,
$timestamp
将包含第一列。。虽然我想让它看起来像原来的一样,但这只会替换文件最后一行的时间戳。需要更多的引号才能正确<代码>回显“$line”
,而不是
回显$line
cp“$infle”
,等等。事实上,要获得
时间戳
,只需说
,而IFS=“,”读取时间戳rest
,然后
$timestamp
将包含第一列。是的。。虽然我想让它看起来像原来的一样,但这只会替换文件最后一行的时间戳。需要更多的引号才能正确<代码>回显“$line”,而不是
回显$line
cp“$infle”
等。是的,问题类似,我的处理方式基于您的答复本身。但我这里的问题不在于代码的工作。记录数少了,一切都好。问题出现在超过10万行的地方。就像@NickB所建议的,剩下的瓶颈可能是外部实用程序。请改用
date
。但是,使用单个
sed
脚本而不是重写文件100000次,应该已经快得多了。另外,请注意,在您所在地区以外的地方,您还不能广泛理解这些脚本。@程序员,您的原始脚本与输入长度类似于O(n^2)