是否可以进行过滤,即将 ESC 放在内部引号前面sed,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"
,然后重新访问并将第一个替换为引号,将最后一个替换为引号。详细说明:
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