在 Ubuntu 上进行一些处理后,BASH 脚本挂起

Ibr*_*eem 4 bash text-processing background-process

我一直在 Red Hat 服务器上运行下面的脚本,它工作正常并完成了工作。我提供给它的文件包含 50 万行(大约 500000 行),这就是为什么(为了更快地完成它)我在 while 循环块的末尾添加了一个“&”

但是现在我已经设置了一个带有 8 GB RAM 的桌面,在它上面运行 Ubuntu 18.04,并且运行相同的代码只完成了几千行然后挂起。我阅读了一些关于它的内容并将堆栈限制增加到无限制,但它仍然在 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
Run Code Online (Sandbox Code Playgroud)

输入:

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 )|
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

我感兴趣的输出是第 5 列(用管道分隔|)与最后一列的一部分连接,然后是第三列

xen*_*oid 5

纯sed解决方案:

sed -r 's/^[^|]+\|[^|]+\|([^|]+)\|[^|]+\|([^|]+)\|.+\( .+, ([^ ]+).+/\2:\3,\1/' <in.dat >out.dat
Run Code Online (Sandbox Code Playgroud)


Ole*_*nge 5

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
Run Code Online (Sandbox Code Playgroud)
  • -k 保持顺序,所以输入的第一行/最后一行也将是输出的第一行/最后一行
  • --pipepart 即时拆分文件
  • --block -1 每个 CPU 线程分成 1 个块
  • -a input.txt 要拆分的文件
  • doit 要调用的命令(或 bash 函数)

Speedwise parallel(黄色)版本tr在我的系统上优于(黑色)大约 200 MB(秒对 M​​B):

图形

  • +1; 感谢您展示如何使用并行:-) (2认同)
  • 很酷的图。而且,顺便说一句,很高兴从这个很棒的工具的作者那里获得“并行”解决方案。:-) 只是为了我的理解:X 轴是文件大小,Y 轴是处理时间,黄色是“平行”,黑色是“tr”?/// 我在使用和不使用`parallel` 的情况下尝试了我的Perl 解决方案,并得出结论,在这种特殊情况下,`parallel` 的改进很小。我认为实际文件很小,并且“并行”无法补偿其处理所需的开销_在这种情况下_。 (2认同)

Per*_*uck 3

Perl解决方案

该脚本不会并行执行任何操作,但无论如何速度都相当快。将其另存为filter.pl(或您喜欢的任何名称)并使其可执行。

#!/usr/bin/env perl

use strict;
use warnings;

while( <> ) {
    if ( /^(?:[^|]+\|){2}([^|]+)\|[^|]+\|([^|]+)\|[^,]+,\s*(\S+)/ ) {
        print "$2:$3,$1\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

我复制了您的示例数据,直到获得 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
Run Code Online (Sandbox Code Playgroud)

如果您喜欢单行,请执行以下操作:

perl -lne 'print "$2:$3,$1" if /^(?:[^|]+\|){2}([^|]+)\|[^|]+\|([^|]+)\|[^,]+,\s*(\S+)/;' < input.txt > output.txt
Run Code Online (Sandbox Code Playgroud)

  • 我最终用 `awk` 制作了一个 oneliner,它与 `perl` oneliner 相当(在我的计算机上稍快一些),如果您将来需要的话,也许更容易理解和编辑。对于测试用例来说,这两个 oneliner 的输出完全相同。看我回答的最后。这两种解决方案中的任何一种都应该适合您。 (2认同)