Лучше откажись от bash'а и возьми нормальный язык программирования - python, perl, ruby, c, c++, java и т.д.. Bash (и тем более POSIX shell) для такого не предназначен и любое решение будет кривым костылём.
>Лучше откажись от bash'а и возьми нормальный язык программирования - python, perl, ruby, c, c++, java и т.д.. Bash (и тем более POSIX shell) для такого не предназначен и любое решение будет кривым костылём.
Да я в общем в курсе как это делать на перле. Просто perl/python/ruby мне по ряду причин не подходят, а писать на c я если честно побаиваюсь.
> Всё было бы идеально, но символы конца строки почему-то превращаются в пробелы.
А ещё могут возникнуть проблемы с мультибайтовыми кодировками (utf8 например). Причём это как повезёт с конкретной сборкой. Я вот после перехода с дженты на убунту обнаружил, что некоторые из моих старых bash-скриптов стали работать неправильно. Пришлось вычищать "башизмы" и делать совместимыми с posix shell, чтобы наверняка.
Небольшой концепт:
$ cat file
Превед медведЪ
шРЕВТЫ ГАВНо
$ IFS=''; sed "s/\(.\)/\1\n/g" file | while read c; do [ -z "${c}" ] && c=$'\n';echo "c = '${c}'"; done
c = 'П'
c = 'р'
c = 'е'
c = 'в'
c = 'е'
c = 'д'
c = ' '
c = 'м'
c = 'е'
c = 'д'
c = 'в'
c = 'е'
c = 'д'
c = 'Ъ'
c = '
'
c = 'ш'
c = 'Р'
c = 'Е'
c = 'В'
c = 'Т'
c = 'Ы'
c = ' '
c = 'Г'
c = 'А'
c = 'В'
c = 'Н'
c = 'о'
c = '
'
Можно попробовать плясать от этого...
Хороший вариант. Только никак в толк не возьму какого чёрта из цикла не извлекаются никакие переменные. Например если собирать все символы в новую строку внутри цикла, то после его выполнения она (строка) будет пустой.
> Хороший вариант. Только никак в толк не возьму какого чёрта из цикла не извлекаются никакие переменные. Например если собирать все символы в новую строку внутри цикла, то после его выполнения она (строка) будет пустой.
Потому-что цикл работает в отдельно форкнутом процессе bash'а. Соответственно переменные среды "наверх" никак не передать. Можно результат выполнения кода в цикле вывести на stdout или например в fifo.
>Потому-что цикл работает в отдельно форкнутом процессе bash'а.
Весьма неожиданно (хотя кажется читал о чём-то подобном когда-то). С чего бы вдруг? for себе такого вроде бы не позволяет. Это плохо. У меня в цикле водится счётчик на основании которого проверяется корректность выполнения цикла. Конечно можно записывать его в файл. К концу этого треда я сделаюсь башененавистником.
> Весьма неожиданно (хотя кажется читал о чём-то подобном когда-то). С чего бы вдруг? for себе такого вроде бы не позволяет.
Bash там форкается дважды. В первый раз - для выполнения sed (exec). И во-второй - для выполнения while read c; do ... done. А нужно это, чтобы stdout первого форка с sed'ом можно было соединить с stdin воторого форка (while read).
> Это плохо. У меня в цикле водится счётчик на основании которого проверяется корректность выполнения цикла. Конечно можно записывать его в файл.
Не обязательно в файл:
result=$(
IFS=''
sed "s/\(.\)/\1\n/g" file | (
cnt=0
while read c; do
[ "${c}" = "е" ] && cnt=$(( $cnt + 1 ))
done
echo "${cnt}"
)
)
echo "Result: ${result}"
Вон Komintern правильно говорит. Возможно всё что тебе нужно можно реализовать на awk без bash'а.
ЛОР не торт. Столько нафлеймили, а еще никто не вспомнил про то, что понятие символа не очень четко определено в задаче. Учитывать ли локаль? Или предполагать утф8? Или автор имеет в виду байты? Что делать с управляющими символами?
>а еще никто не вспомнил про то, что понятие символа не очень четко определено в задаче. Учитывать ли локаль? Или предполагать утф8? Или автор имеет в виду байты?
Вкратце затрагивали. Решили, что считывать побайтово аки dd -- не круто. Мнение автора, видимо, не важно.
Может так пойдёт?
-----------------
#!/bin/bash
while read -n 1 c
do
echo $c
# Ну там и символ из $c ещё как-нибудь обработать.
done < input_file
# А здесь и все переменные из цикла целыми останутся. :)
------------------
Или сразу в массив:
------------------
#!/bin/bash
a=($(while read -n 1 c
do
echo $c
done < input_file))
------------------