
ist es möglich zu filtern, also ESC vor die inneren Anführungszeichen zu setzen mitsed,awkoder ein anderes *NIX-Tool (kein Perl/Python)?
Beispiel (überarbeitet):
$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | magic-filter
label="123 \"456\" 789\" \"AB C" e f gh
label="123 \"456\" 789" "AB C"
Mit anderen Worten wird ein Filter benötigt, der folgendermaßen filtert: der erste und der letzte"char wird unverändert übergeben, alle anderen"wird ersetzt durch\gefolgt von".
Antwort1
Mit GNU sed
, das unterstütztErsetzen aller Vorkommen aus einer bestimmten Anzahl
$ 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
Alle "
(außer dem ersten "
) werden durch ersetzt \"
und dann \
wird vom letzten entfernt\"
Wenn GNU sed
nicht verfügbar, auch \
von zuerst entfernen\"
$ 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
Hinweis: Einige sed
Versionen benötigen möglicherweise -r
statt-E
Mitperl
$ 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
Dabei werden der String bis zur ersten "
und der String von der letzten "
bis zum Ende der Zeileübersprungenwährend die übrigen "
ersetzt werden durch\"
Antwort2
sed
zur Rettung.
sed 's/"/\x1b"/g;s/\x1b"/"/;s/\(.*\)\x1b"/\1"/'
Ersetzen Sie alle Anführungszeichen durch ESC"
und ersetzen Sie dann das erste durch ein einfaches Anführungszeichen und das letzte durch ein einfaches Anführungszeichen. Detaillierte Erklärung:
s/"/\x1b"/g
: Ersetzen Sie alle Anführungszeichen durch \x1b (ESC) und Anführungszeichen.s/\x1b"/"/
: Ersetzen Sie die erste Kombination aus \x1b (ESC) und Anführungszeichen durch ein einfaches Anführungszeichen.s/\(.*\)\x1b"/\1"/
: Ersetzen Sie die abschließende Kombination aus \x1b (ESC) und Anführungszeichen durch ein einfaches Anführungszeichen.
Beispielausgabe:
$ 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
$
Antwort3
Es gibt eine Möglichkeit, das Gewünschte in mehreren Schritten zu erhalten:
Angenommen, eine Variable könnte die Zeichenfolge enthalten (die Zeichenfolge enthält keine einfachen Anführungszeichen):
$ label='label=\"123 \"456\" 789\" \"AB C\" e f gh'
Wir könnten den Teil nach dem herausschneiden \"
:
$ front=${label%\\\"*}
$ echo "$front"
\"123 \"456\" 789\" \"AB C
Entfernen Sie dann bis zum ersten \"
:
$ mid=${front#*\"}
$ echo "$mid"
123 \"456\" 789\" \"AB C
Alle ersetzen \"
durch \e"
:
$ final=${mid//\\\"/\\e}
$ echo "$final"
123 \e456\e 789\e \eAB C
Und schließlich rekonstruieren Sie den ursprünglichen String und verwenden printf für die Escape-Zeichen:
$ 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