
можно ли фильтровать, т.е. ставить ESC перед внутренними кавычкамисед,awkили другой инструмент *NIX (без perl/python)?
Пример (исправленный):
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | magic-filter
label="123 \"456\" 789\" \"AB C" e f gh
метка="123 \"456\" 789" "AB C"
Другими словами, необходим фильтр, который будет фильтровать следующим образом: первый и последний"char будет передан как есть, но все остальные"будет заменен на\с последующим".
решение1
С GNU sed
, который поддерживаетзамена всех вхождений из определенного количества
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh |
sed -E 's/"/\\"/2g; s/\\("[^"]*)$/\1/'
label="123 \"456\" 789\" \"AB C" e f gh
Все "
(кроме первого "
) заменяются на \"
и затем \
удаляются из последнего\"
Если GNU sed
нет в наличии, удалите также и \
из первого .\"
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh |
sed -E 's/"/\\"/g; s/\\"/"/; s/\\("[^"]*)$/\1/'
label="123 \"456\" 789\" \"AB C" e f gh
Примечание: в некоторых sed
версиях может потребоваться -r
вместо-E
Сperl
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh |
perl -pe 's/(^[^"]*"|"[^"]*$)(*SKIP)(*F)|"/\\"/g'
label="123 \"456\" 789\" \"AB C" e f gh
Здесь строка до первой "
и строка от последней "
до конца строки — этопропущенов то время как остальные "
заменяются на\"
решение2
sed
в помощь.
sed 's/"/\x1b"/g;s/\x1b"/"/;s/\(.*\)\x1b"/\1"/'
Заменить все кавычки на ESC"
и затем вернуться и заменить first на just quote, и заменить final на just quote. Подробное объяснение:
s/"/\x1b"/g
: заменить все символы кавычек на \x1b (ESC) и кавычки.s/\x1b"/"/
: заменить первую комбинацию \x1b (ESC) и кавычек на одинарную кавычку.s/\(.*\)\x1b"/\1"/
: заменить финальную комбинацию \x1b (ESC) и кавычек на одинарную кавычку
Пример вывода:
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh |sed 's/"/\x1b"/g;s/\x1b"/"/;s/\(.*\)\x1b"/\1"/'|od -c
0000000 l a b e l = " 1 2 3 033 " 4 5 6
0000020 033 " 7 8 9 033 " 033 " A B C "
0000040 e f g h \n
0000050
$
решение3
Есть способ получить то, что вы просите, в несколько шагов:
предположим, что переменная может содержать строку (строка не имеет одинарных кавычек):
$ label='label=\"123 \"456\" 789\" \"AB C\" e f gh'
Мы могли бы вырезать часть после \"
:
$ front=${label%\\\"*}
$ echo "$front"
\"123 \"456\" 789\" \"AB C
Затем удалите до первого \"
:
$ mid=${front#*\"}
$ echo "$mid"
123 \"456\" 789\" \"AB C
Заменить все \"
на \e"
:
$ final=${mid//\\\"/\\e}
$ echo "$final"
123 \e456\e 789\e \eAB C
И наконец, восстановим исходную строку и используем printf для экранирования:
$ printf "label=\"${front%%\\\"*}$final\"${label#"${front}"}\n"
label="123 456 789 AB C"" e f gh
$ printf "label=\"${front%%\\\"*}$final\"${label#"${front}"}\n" | od -vAn -t x1c
6c 61 62 65 6c 3d 22 31 32 33 20 1b 22 34 35 36
l a b e l = " 1 2 3 033 " 4 5 6
1b 22 20 37 38 39 1b 22 20 1b 22 41 42 20 43 22
033 " 7 8 9 033 " 033 " A B C "
22 20 65 20 66 20 67 68 0a
" e f g h \n