Сценарий Bash зависает после некоторой обработки на Ubuntu

Я работал ниже сценария на сервере Red Hat, и он хорошо работает и заканчивает задание. Файл я подаю его, содержит полмиллиона строк в нем (приблизительно 500 000 строк), и вот почему (для окончания его быстрее) я добавил '&' в конце блока цикла с условием продолжения

Но теперь я имею, устанавливают Рабочий стол с 8 ГБ RAM под управлением Ubuntu 18.04 на нем, и выполнение того же кода только заканчивает несколько тысяч строк и затем зависает. Я читал немного об этом и увеличил предел стека неограниченному также, и тем не менее это зависло приблизительно после 80000 строк, Каких-либо предложений о том, как я могу оптимизировать код или настроить мои параметры ПК, чтобы всегда закончить задание?

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

мой вывод интереса является 5-м столбцом (разделенный с каналом | ) быть связанным с частью последнего столбца и затем третьего столбца

4
задан 1 February 2019 в 01:10

5 ответов

Решение

для 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
3
ответ дан 23 November 2019 в 11:35
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 в 1 блок на поток ЦП
  • -a input.txt файл для разделения
  • doit команда (или функция удара) для вызова

Speedwise parallel (желтая) версия превосходит по характеристикам tr (черные) приблизительно 200 МБ в моей системе (Секунды по сравнению с МБ):

graph

5
ответ дан 23 November 2019 в 11:35

Чистое sed решение:

sed -r 's/^[^|]+\|[^|]+\|([^|]+)\|[^|]+\|([^|]+)\|.+\( .+, ([^ ]+).+/\2:\3,\1/' <in.dat >out.dat
5
ответ дан 23 November 2019 в 11:35

Python

import sys,re

pattern=re.compile(r'^.+\|.+\|(.+)\|.+\|(.+)\|.+, (.+) \)\| 

(работы и с Python2 и с Python3)

Используя regex с нежадными соответствиями 4x быстрее (старается не отслеживать в обратном порядке?) и помещает 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))
) for line in sys.stdin: match=pattern.match(line) if match: print(match.group(2)+':'+match.group(3)+','+match.group(1))

(работы и с Python2 и с Python3)

Используя regex с нежадными соответствиями 4x быстрее (старается не отслеживать в обратном порядке?) и помещает 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))
2
ответ дан 23 November 2019 в 11:35

Остроты мной и другими людьми, а также некоторыми сценариями протестированы

Если порядок пунктов и разделителей может отличаться от того, что Вы указываете в вопросе, я думал, что следующая острота сделает это,

< input tr ' ' '|' | cut -d '|' -f 4,6,10 > output

но в комментарии Вы записали необходимость точно в указанном формате.

Я добавил решение с 'awk', который приблизительно на одном уровне с решением PerlDuck с perl. Посмотрите конец этого ответа.

< input awk '{gsub("\\|"," "); print $5 ":" $9 "," $3}' > output

Тест острот и маленьких сценариев

Тест был сделан в моем компьютере с Lubuntu 18.04.1 LTS, 2*2 процессора и 4 гибибайта RAM.

Я сделал огромное infile путем 'удвоения 20 раз' из демонстрации input (1 572 864 строки), так некоторое поле к Вашим 500 000 строк,

Острота с cut и sed:

$ < infile cut -d '|' -f 3,5,6 | sed -e 's/|[A-Z].*, /|/' -e 's/ )$//' > outfile
$ wc -l infile
1572864 infile
$ wc -l outfile
1572864 outfile
$ tail outfile
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1

Синхронизация

Мы могли бы ожидать, что чистое sed решение было бы быстрее, но я думаю, что переупорядочение данных замедляет его, так, чтобы cut и sed решение быстрее. Оба решения работают без любой проблемы в моем компьютере.

Острота с cut и sed:

$ time < infile cut -d '|' -f 3,5,6 | sed -e 's/|[A-Z].*, /|/' -e 's/ )$//' > outfile

real    0m8,132s
user    0m8,633s
sys     0m0,617s

Чистое sed острота xenoid:

$ time sed -r 's/^[^|]+\|[^|]+\|([^|]+)\|[^|]+\|([^|]+)\|.+\( .+, ([^ ]+).+/\2:\3,\1/' <infile > outfile-sed 

real    1m8,686s
user    1m8,259s
sys     0m0,344s

A python сценарий с помощью regex с нежадными соответствиями xeniod:

#!/usr/bin/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))

$ time < infile ./python-ng > outfile.pyng

real    0m8,055s
user    0m7,359s
sys 0m0,300s

$ python --version
Python 2.7.15rc1

A perl острота PerlDuck быстрее, чем предыдущие остроты:

$ time perl -lne 'print "$2:$3,$1" if /^(?:[^|]+\|){2}([^|]+)\|[^|]+\|([^|]+)\|[^,]+,\s*(\S+)/;' < infile > outfile.perl

real    0m5,929s
user    0m5,339s
sys     0m0,256s

Острота с tr и cut с a tr -s команда:

Я использовал tr преобразовать пробелы во входном файле для конвейерной обработки символов и затем cut мог сделать все это без sed.Как видете, tr намного быстрее, чем sed. tr -s команда удаляет двойные каналы во входе, который является хорошей идеей, особенно если там может быть повторен пробелы или каналы во входном файле. Это не стоит многого.

$ time < infile tr ' ' '|' | tr -s '|' '|' | cut -d '|' -f 3,5,9 > outfile-tr-cut

real    0m1,277s
user    0m1,781s
sys     0m0,925s

Острота с tr и cut без tr -s команда, самая быстрая до сих пор:

time < infile tr ' ' '|' | cut -d '|' -f 4,6,10 > outfile-tr-cut

real    0m1,199s
user    0m1,020s
sys     0m0,618s


$ tail outfile-tr-cut
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.SERV1
12-654-0330|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT81.C1.P1
12-664-1186|202-00_MSRFKH00OL6|R1.S1.LT7.PON8.ONT75.SERV1

Острота с awk, быстро, но не самое быстрое,

< input awk '{gsub("\\|"," "); print $5 ":" $9 "," $3}' > output

$ time < infile awk '{gsub("\\|"," "); print $5 ":" $9 "," $3}' > outfile.awk

real    0m5,091s
user    0m4,724s
sys     0m0,365s

awk с parallel реализованный по словам Ole Tange уменьшает реальное время с 5 с до 2 с:

#!/bin/bash

doit() {
 awk '{gsub("\\|"," "); print $5 ":" $9 "," $3}'
}
export -f doit
parallel -k --pipepart --block -1 -a infile doit > outfile.parallel-awk

$ time ./parallel-awk 
# Academic tradition requires you to cite works you base your article on.
# When using programs that use GNU Parallel to process data for publication
#please cite:

#  O. Tange (2011): GNU Parallel - The Command-Line Power Tool,
#  ;login: The USENIX Magazine, February 2011:42-47.

# This helps funding further development; AND IT WON'T COST YOU A CENT.
#If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

# To silence this citation notice: run 'parallel --citation'.

real    0m1,994s
user    0m5,015s
sys     0m0,984s

Мы можем ожидать что преимущество с parallel увеличится с большим размером входного файла, как описано схемой в ответе Ola Tange на этот вопрос.

Сводка скорости: 'реальное' время согласно time округленный к 1 десятичному числу

1m 8.7s - sed
   8.1s - cut & sed
   7.4s - python
   5.9s - perl
   5.1s - awk
   2.0s - parallel & awk
   1.2s - tr & cut

Наконец, я отмечаю что остроты с sed, python, perl, awk и {parallel & awk} создают выходной файл с предписанным форматом.

$ tail outfile.awk
202-00_MSRFKH00OL6:R1.S1.LT7.PON8.ONT75.SERV1,12-664-1186
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
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
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
3
ответ дан 23 November 2019 в 11:35

Другие вопросы по тегам:

Похожие вопросы: