Я не уверен в составе вашего тестового файла (сколько нужно замен?), Поэтому я не могу точно воспроизвести ваш тест, но я использую мой / bin / bash (1168776 байт в 5714 "строк ", с 372073 (31,8%) печатными символами / символами табуляции).
sed
(базовый уровень для целей синхронизации)
$ cp /bin/bash sh; time sed -i $'s/[^[:print:]\t]//g' sh
sed -i $'s/[^[:print:]\t]//g' sh 1.66s user 0.01s system 98% cpu 1.687 total
$ cp /bin/bash sh; time sed -i $'s/[^[:print:]\t]//g' sh
sed -i $'s/[^[:print:]\t]//g' sh 1.74s user 0.01s system 89% cpu 1.945 total
$ cp /bin/bash sh; time sed -i $'s/[^[:print:]\t]//g' sh
sed -i $'s/[^[:print:]\t]//g' sh 1.67s user 0.01s system 97% cpu 1.718 total
Среднее среднее общее время = 1,778s ? (важно запустить несколько раз для контроля за кэшированием. Я запустил четыре раза и бросил первый для учета кэширования, а затем усреднил, чтобы контролировать внешние эффекты, такие как мой веб-браузер)* Я перевел это на perl, чтобы посмотреть, будет ли это быстрее:
$ cp /bin/bash sh; time perl -i -pe $'s/[^[:print:]\t]//g' sh
perl -i -pe $'s/[^[:print:]\t]//g' sh 0.18s user 0.01s system 92% cpu 0.208 total
$ cp /bin/bash sh; time perl -i -pe $'s/[^[:print:]\t]//g' sh
perl -i -pe $'s/[^[:print:]\t]//g' sh 0.18s user 0.01s system 68% cpu 0.271 total
$ cp /bin/bash sh; time perl -i -pe $'s/[^[:print:]\t]//g' sh
perl -i -pe $'s/[^[:print:]\t]//g' sh 0.21s user 0.00s system 81% cpu 0.258 total
Среднее среднее общее время = 0,246 с ?
Однако я заметил некоторые различия. GNU sed
испытывает трудности, возможно, из-за другого определения класса [:print:]
или (более вероятно) различной обработки управляющих символов:
$ sed $'s/[^[:print:]\t]//g' /bin/bash |head -c64 |hd
00000000 45 4c 46 3e 30 f6 40 48 ce 40 38 40 40 40 40 68 |ELF>0.@H.@8@@@@h|
00000010 68 a8 a8 a8 98 cd 98 cd d0 d0 d0 8d d7 0a 8d d7 |h...............|
00000020 0a b0 b0 b0 30 57 30 57 f0 f0 23 f0 23 b9 a8 55 |....0W0W..#.#..U|
00000030 f0 3c f0 4c f0 4c c4 c4 c4 44 44 50 e5 74 64 30 |.<.L.L...DDP.td0|
00000040
$ perl -pe $'s/[^[:print:]\t]//g' /bin/bash |head -c64 |hd
00000000 45 4c 46 3e 30 40 48 40 38 40 40 40 40 68 68 30 |ELF>0@H@8@@@@hh0|
00000010 57 30 57 23 23 55 3c 4c 4c 44 44 50 74 64 30 49 |W0W##U<LLDDPtd0I|
00000020 30 49 30 49 44 44 51 74 64 52 74 64 23 23 2c 2c |0I0IDDQtdRtd##,,|
00000030 2f 6c 69 62 36 34 2f 6c 64 2d 6c 69 6e 75 78 2d |/lib64/ld-linux-|
00000040
См. Все эти точки в GNU sed
выход? Это неудачи для замены контента. Я также наблюдаю это в Busybox sed
. BSD sed
(который используется в Mac OS X), по-видимому, не имеет этого ограничения, но учтите это для целей мобильности по мере необходимости.
tr
$ cp /bin/bash sh; time tr -cd $'[ -~\t\n]' < sh > sh-tr && mv sh-tr sh
tr -cd $'[[:print:]\t]' < sh > sh-tr 0.00s user 0.01s system 62% cpu 0.012 total
$ cp /bin/bash sh; time tr -cd $'[ -~\t\n]' < sh > sh-tr && mv sh-tr sh
tr -cd $'[[:print:]\t]' < sh > sh-tr 0.00s user 0.01s system 81% cpu 0.009 total
$ cp /bin/bash sh; time tr -cd $'[ -~\t\n]' < sh > sh-tr && mv sh-tr sh
tr -cd $'[[:print:]\t]' < sh > sh-tr 0.00s user 0.01s system 82% cpu 0.012 total
Среднее среднее значение общеговремена = 0,011 с ⚡️
Я тестировал это с GNU tr
и Busybox tr
(они имеют одинаковую производительность). Мы используем tr
для удаления (-d
) вместо tr anslate, и мы действуем на основе дополнения (-c
) данного класса (tr
делает )не используйте регулярное выражение, поэтому мы не можем инвертировать класс символов с помощью каретки, как мы можем в sed
).
Busybox tr
не поддерживает $'[[:print:]\t]'
, поэтому я преобразовал егов диапазоне от пробела до тильды (все печатаемые нижний ASCII, кроме табуляции и новой строки), и я добавил не только табуляцию, но и новую строку, поскольку tr
необходимо явно сохранить этот символ (sed
не сделал). Если строки не совпадают должным образом, рассмотрите возможность добавления \r
в набор для замены.
strings
здесь также хорошо, но не сохраняет строки (он заменяет каждую смежную строку непечатаемых символовс новой строкой)