我一直在 Red Hat 服务器上运行下面的脚本,它运行良好并完成了任务。我提供给它的文件包含 50 万行(大约 500000 行),这就是为什么(为了更快地完成它)我在 while 循环块末尾添加了一个“&”
但是现在我已经安装了一台运行 Ubuntu 18.04 的 8 GB RAM 台式机,运行相同的代码只完成几千行然后就挂了。我阅读了一些相关内容,并将堆栈限制也增加到无限制,但它仍然在 80000 行左右后挂了,关于如何优化代码或调整我的 PC 参数以始终完成工作,有什么建议吗?
while read -r CID60
do
{
OLT=$(echo "$CID60" | cut -d"|" -f5)
ONID=${OLT}:$(echo "$CID60" | cut -d, -f2 | sed 's/ //g ; s/).*|//')
echo $ONID,$(echo "$CID60" | cut -d"|" -f3) >> $localpath/CID_$logfile.csv
} &
done < $localpath/$CID7360
输入:
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ASSN45| Unlocked|12-654-0330|Up|202-00_MSRFKH00OL6|P282018767.C2028 ( network, R1.S1.LT7.PON8.ONT81.SERV1 )|
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ASSN46| Unlocked|12-654-0330|Down|202-00_MSRFKH00OL6|P282017856.C881 ( local, R1.S1.LT7.PON8.ONT81.C1.P1 )|
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ASSN52| Unlocked|12-664-1186|Up|202-00_MSRFKH00OL6|P282012623.C2028 ( network, R1.S1.LT7.PON8.ONT75.SERV1 )|
输出:
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT81.SERV1,12-654-0330
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT81.C1.P1,12-654-0330
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT75.SERV1,12-664-1186
我感兴趣的输出是第五列(用管道分隔|
)与最后一列的一部分连接,然后是第三列
答案1
纯 sed 解决方案:
sed -r 's/^[^|]+\|[^|]+\|([^|]+)\|[^|]+\|([^|]+)\|.+\( .+, ([^ ]+).+/\2:\3,\1/' <in.dat >out.dat
答案2
doit() {
# Hattip to @sudodus
tr ' ' '|' |
tr -s '|' '|' |
cut -d '|' -f 3,5,9
}
export -f doit
parallel -k --pipepart --block -1 -a input.txt doit > output.txt
-k
保持顺序,因此输入的第一行/最后一行也将是输出的第一行/最后一行--pipepart
即时分割文件--block -1
每个 CPU 线程分成 1 个块-a input.txt
要分割的文件doit
要调用的命令(或 bash 函数)
从速度上看,在我的系统上parallel
,黄色版本比黑色版本快tr
大约 200 MB(秒数与 MB):
答案3
Perl 解决方案
此脚本不会并行执行任何操作,但无论如何速度都相当快。将其另存为filter.pl
(或您喜欢的任何名称)并使其可执行。
#!/usr/bin/env perl
use strict;
use warnings;
while( <> ) {
if ( /^(?:[^|]+\|){2}([^|]+)\|[^|]+\|([^|]+)\|[^,]+,\s*(\S+)/ ) {
print "$2:$3,$1\n";
}
}
我复制了您的示例数据,直到得到 1,572,864 行,然后按如下方式运行:
me@ubuntu:~> time ./filter.pl < input.txt > output.txt
real 0m3,603s
user 0m3,487s
sys 0m0,100s
me@ubuntu:~> tail -3 output.txt
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT81.SERV1,12-654-0330
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT81.C1.P1,12-654-0330
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT75.SERV1,12-664-1186
如果你喜欢单行代码,请执行以下操作:
perl -lne 'print "$2:$3,$1" if /^(?:[^|]+\|){2}([^|]+)\|[^|]+\|([^|]+)\|[^,]+,\s*(\S+)/;' < input.txt > output.txt
答案4
Python
import sys,re
pattern=re.compile(r'^.+\|.+\|(.+)\|.+\|(.+)\|.+, (.+) \)\|$')
for line in sys.stdin:
match=pattern.match(line)
if match:
print(match.group(2)+':'+match.group(3)+','+match.group(1))
(适用于 Python2 和 Python3)
使用非贪婪匹配的正则表达式速度提高了 4 倍(避免回溯?),并使 Python 与 cut/sed 方法相媲美(Python2 比 Python3 快一点)
import sys,re
pattern=re.compile(r'^[^|]+?\|[^|]+?\|([^|]+?)\|[^|]+?\|([^|]+?)\|[^,]+?, (.+) \)\|$')
for line in sys.stdin:
match=pattern.match(line)
if match:
print(match.group(2)+':'+match.group(3)+','+match.group(1))