Удалить значения из файла, разделенного NUL

Будет ли это лучшим примером?

$ time perl -e 'alarm(3); 1 while 1;' | perl -e 'alarm(4); 1 while 1;'
Alarm clock

real    0m4.004s
user    0m6.992s
sys     0m0.004s

Скрипты зацикливаются на 3 и 4 секунды (соответственно. ), занимая всего 4 секунды в реальном времени из-за параллельного выполнения и 7 секунд процессорного времени. (хотя бы приблизительно.)

Или это:

$ time ( sleep 2; echo) | ( read x; sleep 3 )

real    0m5.004s
user    0m0.000s
sys     0m0.000s

Они не выполняются параллельно, поэтому общее время составляет 5 секунд. Все это потрачено на сон, поэтому процессорное время не используется.

2
07.08.2019, 15:47
1 ответ

Основываясь на ваших входных данных и предполагая, что ваш файл достаточно мал, чтобы поместиться в памяти, это может сработать для вас:

$ export i
$ perl -0777 -pe 's/\Q$ENV{i}\E\n?//g' file 
hi
blue boy

-0777заставляет perlзагружать весь файл в память. $ENV{var}— это способ Perl для доступа к экспортируемым переменным среды. Таким образом, $ENV{i}получит значение для экспортируемой переменной i. s/old/new/gзаменит oldна newглобально. \Qи \Eгарантируют, что шаблон не интерпретируется как регулярное выражение. Наконец, \n?необходим, так как оболочка будет потреблять новые строки с концов переменных при назначении вывода подстановки команд (, например. var=$(printf 'foo\n')), поэтому $iна самом деле может не включать последнюю новую строку.

Обратите внимание, что это также будет соответствовать подстрокам. Таким образом, если iравно fooи ваш файл содержит foolish, то fooбудет удалено, оставив ish. Если вы этого не хотите, вы можете использовать:

perl -0777 -pe 's/\Q$ENV{i}\E(\n|\b)//g' file 

Тестирование на вашем примере (после замены ^@на\0):

$ cat -v file
^@this is 1.
this is 2.
this is 3.
^@hi
^@blue boy

$ export i="$(printf 'this is 1.\nthis is 2.\nthis is 3.\n')"

$ perl -0777 -pe 's/\Q$ENV{i}\n?\E//g' file 
hi
blue boy

Конечно, это предполагает, что $iне имеет завершающей новой строки. Я не могу сказать, так это или нет, так как cat <<<"$i"добавил бы один, даже если бы это было не так.

Если вам нужно сделать это для массива оболочки, вы можете сделать:

for i in "${foo[@]}"; do 
    export i
    perl -0777 -i -pe 's/\b\Q$ENV{i}\E(\n|\b)//g' file 
done

Важно:обратите внимание на -iв приведенном выше примере. Это редактирует файл на месте, поэтому сделайте его резервную копию перед тестированием.

1
27.01.2020, 22:02

Теги

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