[Решено] Bash, regexp и кириллица?

Доброго времени суток, %username%.

Есть у нас bash скрипт, который работает на различных платформах (от старенького Debian GNU/Linux 5.0 (Linux 2.6.32.11, bash 3.2.39) до Red Hat 4.8.2 (Linux 3.10.0, bash 4.2.46)). Скрипт этот на входе (в качестве параметра или STDIN) принимает строку, которая содержит много всего. Строка эта обрабатывается, лишнее - вырезается, итог вставляется в JSON-запрос и отправляется дальше. Но столкнулся с задачей, которую решить на данный момент не получается. А заключается она в следующем:

Необходимо составить регулярное выражение, которое будет вырезать все символы, кроме латиницы, кириллицы, чисел и знаков пунктуации.


И всё бы хорошо, в ряде ОС у нас кириллица в исходниках - воспринимается в штыки. Т.е. скрипт работает до тех пор - пока не появится необходимость его отредактировать/поправить. После попытки редактирования, из-за конструкции вида:

string=${string//[^0-9A-Za-zА-Яа-яЁё]/_};

(а именно из-за А-Яа-яЁё) сохранить открытый файл в том же nano - проблематично. Самое на мой взгляд логичное решение - заменить сами символы кириллицы - их кодами, но как? Попытки вида \430-\44f \u430-\u44f \x430-\x44f - не приносят успеха. При просмотре кодов hexdump-ом у нас картинка следующая:

printf 'abcd' | hexdump -C; exit 0;
$ ./test.sh
00000000  61 62 63 64                                       |abcd|
00000004

printf 'абвг' | hexdump -C; exit 0;
$ ./test.sh test
00000000  d0 b0 d0 b1 d0 b2 d0 b3                           |........|
00000008

printf %x "'а"; echo " "; printf %x "'я"; exit 0;
$ ./test.sh test
430
44f

printf %x "'a"; echo " "; printf %x "'z"; exit 0;
$ ./test.sh test
61
7a

Окончательно формирую свой вопрос:

Какой вид должно иметь регулярное выражение (применимое по возможности в чистой среде bash), уделяющее все символы, кроме латиницы, кириллицы, чисел и знаков пунктуации, учитывая что диапазон символов кириллицы должен быть записан в виде диапазона кодов символов, а не самих символов.


Заранее спасибо сообществу.

// данный вопрос задан и на ru.stackoverflow.com
  • Вопрос задан
  • 2443 просмотра
Решения вопроса 1
@Shetani
попробуйте заменить кириллицу диапазонами \xDO\x90-\xd0\xbf и \xd1\x80-\xd1\x8f Ё \xd0\x81 ё \xd1\x91
string=${string//[^0-9A-Za-z\xDO\x90-\xd0\xbf\xd1\x80-\xd1\x8f\xd0\x81\xd1\x91]/_};
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Power
Можно так:
message_text='qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM абв..эюяАБВ..ЭЮЯ 1234567890~!@#$%^&*()_"`'"'"
string="<\!DOCTYPE html><html><body>$message_text</body></html>"

cyrillic=$'\xd0\x90-\xd0\xaf\xd0\xb0-\xd1\x8f\xd0\x81\xd1\x91' # 'А-Яа-яЁё' в utf-8
old_collate=$LC_COLLATE
LC_COLLATE=C # иначе могут быть неочевидные эффекты (например, "À" приравняется к "A")
eval "string=\${string//[^0-9A-Za-z${cyrillic}]/_}" # с eval нужно аккуратно. в данном случае всё OK, он выполнит строку string=${string//[^0-9A-Za-zА-Яа-яЁё]/_}
LC_COLLATE=$old_collate
echo "$string"
Ответ написан
Комментировать
@ShamblerR
1. Кака вариант посикс класы но не факт что прокатит уж больно они новые.
2. Доставь кирилицу как правило это делается на раз два
3. Сделай обратное исключение
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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