内部引用符をフィルタリングするにはどうすればいいですか?

内部引用符をフィルタリングするにはどうすればいいですか?

フィルタリング、つまり、内側の引用符の前にESCを置くことは可能ですか?sedawkまたは他の *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

関連情報