Я уже знаю пару способов прочитать файл через каждые N символов в bash:
LC_ALL=C
while read -n100 character; do
echo "$character"
done < <(cat "$@" | tr -d '\n')
echo "$character
Но пока это работает, я хотите узнать более быстрые способы сделать это либо в Bash, либо с помощью инструментов posix/unix.
Есть ли другой способ сделать это быстрее?
Попробуйте это awk
решение, которое работает со многими, но не со всеми awk
реализациями из-за использования расширения "пустой разделитель полей":
awk -F "" -v l=100 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==0) {print $i; last=i}};\
if (last) {carry=NF-last} else {carry+=(NF-l)}}' inputfile.txt
Это будет обрабатывать каждый символ как одно поле(-F ""
)и печатать только те поля, где номер поля по модулю «длина пропуска»l
(в вашем случае 100 )равен нулю, принимая во внимание перенос -над, но без учета новых строк.
Обратите внимание, что поскольку счет начинается с 1, первый символ , а не считывается. Вы можете использовать
awk -F "" -v l=10 -v ofs=1 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==ofs) {print $i; last=i}};\
if (last) {carry=NF-last+ofs} else {carry+=(NF-l)}}' inputfile.txt
, чтобы отрегулировать смещение с помощью ofs
.
Протестировано с gawk
, mawk
и nawk
в системе Linux.
12345678901234
567890123
4567890123456789012
34567890123
$ awk -F "" -v l=10 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==0) {print $i; last=i}}; if (last) {carry=NF-last} else {carry+=(NF-l)}}' testfile.txt
0
0
0
0
0
$ awk -F "" -v l=10 -v ofs=1 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==ofs) {print $i; last=i}}; if (last) {carry=NF-last+ofs} else {carry+=(NF-l)}}' testfile.txt
1
1
1
1
1
1
Копирование результата AdminBee с несколько более простым кодом.
Входные данные такие же, как у них:
12345678901234
567890123
4567890123456789012
34567890123
Каждый 10-й символ, начиная с 10:
$ fold -w 1 file | awk 'NR % 10 == 0'
0
0
0
0
0
То же самое, но начиная с 1:
$ fold -w 1 file | awk 'NR % 10 == 1'
1
1
1
1
1
1
То же, но начиная с 2:
$ fold -w 1 file | awk 'NR % 10 == 2'
2
2
2
2
2
2
С точки зрения производительности это сравнимо с решением AdminBee awk
, но немного быстрее на больших входных данных ("большие входные данные" == приведенные выше тестовые данные повторяются много раз ).
fold -w 1
создает одну строку для каждого символа ввода, отбрасывая символы новой строки. Обе используемые команды являются стандартными утилитами POSIX.