2014-12-24 2 views
2

У меня есть скрипт для создания полукокса массивов из строк:Экранирование специальных символов с СЕПГ

#!/bin/bash 
while [ -n "$1" ] 
do 
    echo -n "{" && echo -n "$1" | sed -r "s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}" 
    shift 
done 

Он прекрасно работает как:

$ wchar 'test\n' 'test\\n' 'test\123' 'test\1234' 'test\x12345' 
{'t','e','s','t','\n',0} 
{'t','e','s','t','\\','n',0} 
{'t','e','s','t','\123',0} 
{'t','e','s','t','\123','4',0} 
{'t','e','s','t','\x12345',0} 

Но поскольку СЭД рассматривает каждую новую строку, чтобы быть совершенно новая вещь не обрабатывает фактические строки перевода строки:

$ wchar 'test 
> test' 
{'t','e','s','t', 
't','e','s','t',0} 

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

$ wchar 'test 
> test' 
{'t','e','s','t','\n','t','e','s','t',0} 

Edit: Некоторые идеи, которые практически работают:

echo -n "{" && echo -n "$1" | sed -r ":a;N;;s/\\n/\\\\n/;$!ba;s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}" 

Производит:

$ wchar 'test\n\\n\1234\x1234abg 
test 
test' 
{test\n\\n\1234\x1234abg\ntest\ntest0} 

В то время как удаление !:

echo -n "{" && echo -n "$1" | sed -r ":a;N;;s/\\n/\\\\n/;$ba;s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}" 

Производит:

$ wchar 'test\n\\n\1234\x1234abg 
test 
test' 
{'t','e','s','t','\n','\\','n','\123','4','\x1234ab','g','\n','t','e','s','t', 
test0} 

Это близко ...

Первый не выполняет окончательную замену, а второй не правильно добавив последнюю строку

+0

Я хотел бы рассмотреть разбор выхода 'ода -c' вместо' sed' –

+0

@JV, интересно, если ваш выход на самом деле правильно: 'эхо -ne«теста \ x12345» | od -c' выдает '0000000 t e s t 022 3 4 5', интерпретируя' \ x12' как один символ, а не '\ x12345' –

+0

@ nu11p01n73R: Это приглашение оболочки для новой строки. –

ответ

3

Вы можете предварительно фильтр перед переходом к sed. Perl будет делать:

$ set -- 'test1 
> test2' 
$ echo -n "$1" | perl -0777 -pe 's/\n/\\n/g' 
test1\ntest2 
1

Это очень запутанное решение, но может работать для ваших нужд. GNU AWK 4,1

#!/usr/bin/awk -f 
@include "join" 
@include "ord" 
BEGIN { 
    RS = "\\\\(n|x..)" 
    FS = "" 
} 
{ 
    for (z=1; z<=NF; z++) 
    y[++x] = ord($z)<0x20 ? sprintf("\\x%02x",ord($z)) : $z 
    y[++x] = RT 
} 
END { 
    y[++x] = "\\0" 
    for (w in y) 
    y[w] = "'" y[w] "'" 
    printf "{%s}", join(y, 1, x, ",") 
} 

Результат

$ cat file 
a 
b\nc\x0a 

$ ./foo.awk file 
{'a','\x0a','b','\n','c','\x0a','\0'} 
+0

Мне нравится, как это автоматически обрабатывает экранирование специальных символов - есть ли способ удалить пробелы между выходными символами? Это будет в основном делать то, что я ищу –

+0

Я говорю о 'od' на своем собственном - есть ли способ удалить отступ, используемый для разделения символов? –

+0

Если файл содержит escape-последовательность (как прочитано GCC), он должен быть воспроизведен как символ. Входная строка 'test \ ntest \ x0A' должна выводить' {'t', 'e', ​​'s', 't', '\ n', 't', 'e', ​​'s', 't', ' '\ x0A', 0} 'Ваше разделяет escape-последовательности на отдельные символы. –

Смежные вопросы