Альтернатива Sed для поиска и замены на очень длинных строках

Нет никакой команды, о которой я знаю, но там существует libc вызов функции, который может получить статистику:

человек 3 mq_getattr

   mq_getattr() returns an mq_attr structure  in  the  buffer  pointed  by
   attr.  This structure is defined as:

       struct mq_attr {
           long mq_flags;       /* Flags: 0 or O_NONBLOCK */
           long mq_maxmsg;      /* Max. # of messages on queue */
           long mq_msgsize;     /* Max. message size (bytes) */
           long mq_curmsgs;     /* # of messages currently in queue */
       };
9
02.03.2015, 17:26
4 ответа

Можно использовать другой инструмент, позволяющий установить разделитель входных записей. Например

  • Perl

    perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
    

    Специальная переменная $/ - это разделитель входных записей. Установка ее на }{ определяет строки как оканчивающиеся на }{. Таким образом, можно добиться желаемого без считывания всей информации в память.

  • mawk или gawk

    awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file 
    

    Это та же самая идея. RS="}{" устанавливает разделитель записей на }{, а затем печатает }, новую строку, { (кроме первой записи) и текущую запись.

7
27.01.2020, 20:06

Вы должны сделать:

{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile

Это, вероятно, самое эффективное решение.

Это ставит {} , чтобы защитить любые возможные задние данные. Благодаря еще одному процессу TR , который вы можете поменять обмен этим и выполнять пустую строку во главе первого { поле. Как ...

tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}

Так что первое, с примером дона данных, делает:

printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; }           |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}

... а второй делает ...

printf '{one}{two}{three}{four}'      |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}

Нет трейлинга новой строки для второго примера - хотя есть один для первое.

2
27.01.2020, 20:06

Perl к спасению:

perl -i~ -e ' $/ = \1024;
              while (<>) {
                  print "\n" if $closing and /^{/;
                  undef $closing;
                  s/}{/}\n{/g;
                  print;
                  $closing = 1 if /}$/;
              } ' input1 input2

Установка $ / - \ 1024 будет прочитать файл в кусках 1024 байта. Переменная $ Caking $ Caking переменная обрабатывает корпус при заканчивании куска в } } и следующий запускается с {.

3
27.01.2020, 20:06

Двоичнаяsed-подобная утилита под названиемbbe

Мне кажется, что в этом случае проще всего использовать синтаксис sed -.

Ягораздопредпочитаю использовать bbeутилиту (, доступную через установку пакета {uni,linu}x, например.apt-get). Или здесь , если вы один из толпы git, хотя я лично не проверял эту конкретную ссылку.

1. Поддерживает идиому s/before/after/

Это «редактор двоичных блоков», который поддерживает sed -, например (, среди прочих операций ). Это включает в себя очень распространенную идиому замены s/before/after/, которая вам нужна. Обратите внимание, поскольку с точки зрения bbeнет строк как таковых, в конце команды нет «глобальной буквы g».

В качестве быстрой проверки (обратите внимание на необходимое-e):

$ echo hello | bbe -e 's/l/(replaced)/'

производит:

he(replaced)(replaced)o

2. В вашем конкретном случае преобразования }{в }\n{

Таким образом, если бы у нас был массивный файл, заполненный миллионом чисел в (, скажем, )в формате {1}{2}{3}... {1000000}без возврата каретки, мы могли бы заменить }{на }\n{легко и иметь все числа по одному в строке.

Это будет с этой bbeкомандой:

bbe -e 's/}{/}\n{/'

Как проверено в этом цикле zsh, который мы захватываем только за конец:

$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail

Который произведет это:

{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}

(без конечного возврата каретки.)

1
22.04.2020, 23:00

Теги

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