wie filtert man innere Anführungszeichen?

wie filtert man innere Anführungszeichen?

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 sednicht 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 sedVersionen benötigen möglicherweise -rstatt-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

sedzur 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

verwandte Informationen