Я работал ниже сценария на сервере 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-м столбцом (разделенный с каналом |
) быть связанным с частью последнего столбца и затем третьего столбца
для 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
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 МБ в моей системе (Секунды по сравнению с МБ):
Чистое sed решение:
sed -r 's/^[^|]+\|[^|]+\|([^|]+)\|[^|]+\|([^|]+)\|.+\( .+, ([^ ]+).+/\2:\3,\1/' <in.dat >out.dat
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))
Если порядок пунктов и разделителей может отличаться от того, что Вы указываете в вопросе, я думал, что следующая острота сделает это,
< 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