Удаление непечатаемых символов с помощью POSIX sed

Хорошо, таким образом, вот то, где история запускается: https://bugs.freedesktop.org/show_bug.cgi? id=42931 кажется, что кому-то не нравилось старое поведение, таким образом, это было изменено на однонаправленный.

Хотя страница справочника в моем xkeyboard-config-2.6 не имеет всех опций поддерживаемыми, существуют опции переключателя _bidir, которые можно использовать. Таким образом для восстановления старого поведения конфигурация (или соответствующая команда setxkbmap) должна быть похожей на это:

Section "InputClass"
    Identifier "keyboard-all"
    MatchIsKeyboard "on"
    Driver "evdev"
    Option "XkbLayout" "us,ru,de"
    Option "XkbVariant" ",winkeys,"
    Option "XkbOptions" "terminate:ctrl_alt_bksp,grp:ctrl_shift_toggle_bidir"
EndSection

2
17.07.2014, 05:44
1 ответ

Можете ли вы сделать это только , используя POSIX sed ? Да:

sed -e 's/.^H//g' < data

где ^H - это просто буквальный символ обратного пробела. POSIX sed использует POSIX основные регулярные выражения, которые определяются через байты - печатают символы или нет, их не волнует, так что это ведет себя так же, как если бы ^H была буква. Здесь нет никаких расширений. Обратите внимание, что все, что вы действительно хотите сделать, это удалить символы, которые были разнесены назад, поэтому группы захвата в вашем примере на самом деле не нужны.

В большинстве случаев вы можете ввести символ обратного пробела с помощью Ctrl+V Ctrl+H.

Я думаю, что скрытый вопрос, который у Вас есть - "как это сделать в скрипте оболочки?", где буквальный символ обратного пробела может быть неприятен для работы (хотя vim с радостью примет тот же самый Ctrl+V Ctrl+H, чтобы записать один из них). В этом введении вы использовали tr.

POSIX tr поддерживает различные экранирующие символы , в том числе символический \b экранирующий символ для обратного пробела. Символ обратного пробела можно сохранить в переменную и заменить эту переменную в выражении sed, приведенном выше:

BACKSPACE=$(echo x | tr 'x' '\b')
sed -e "s/.$BACKSPACE//g" < data

Мы просто скажем tr заменить x на символ обратного пробела, и дадим ему единственный x в качестве входного. Это прекрасно работает на всех системах, к которым у меня есть доступ, включая Solaris. Однако, printf также является инструментом, определяемым POSIX, и он поддерживает те же эквапсы:

BACKSPACE=$(printf '\b')
sed -e "s/.$BACKSPACE//g" < data

Это проще и прямее, чем tr версия. Обратите внимание на двойное цитирование вокруг выражения sed, так что мы больше не подавляем интерполяцию переменных. Вы также можете использовать подстановку command substitution inline, чтобы поместить printf '\b' непосредственно, если вы собираетесь использовать его только один раз, вместо того, чтобы использовать переменную.

Мы можем проверить, что это работает с помощью hexdump (или hd):

$ dash
$ hexdump -C data
00000000  62 08 62 6f 08 6f 6c 08  6c 64 08 64 0a           |b.bo.ol.ld.d.|
$ BACKSPACE=$(printf '\b')
$ sed -e "s/.$BACKSPACE//g" < data | hexdump -C
00000000  62 6f 6c 64 0a                                    |bold.|

По желанию, символ обратного пространства и стертый предыдущий символ удаляются из вывода (0a является завершающим символом новой строки).

3
27.01.2020, 22:06

Теги

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