3

目標:次の文字列を分割できるようにする:"command/test \/ escaped/"

次のリストに:["command", "test / escaped"]

現在の正規表現は次のようになります。

Str.split (Str.regexp "/") string_to_split;;

これは単純すぎるため、文字列の前にバックスラッシュを付けてエスケープする必要があります。

私はこれを試しました:Str.regexp "((?!\\).)/"しかし、Ocamlパーサーが生成するものでは機能しません:uncaught exception Failure("spurious \) in regular expression")

何か案は?

Ocaml-parser は文字列のバックスラッシュを自動的にエスケープするので、: のような文字列 "foobar\/barfoo""foobar\\/barfoo". したがって、文字列内の偶数のバックスラッシュをすべて実際に削除したい場合があります。

4

3 に答える 3

3

バックスラッシュを 2 回エスケープする必要があります。

  • 文字列コンテンツに対して 1 回
  • 正規表現のために1回

したがって、正しい正規表現はStr.regexp "((?!\\\\).)/".

ただし、その正規表現は機能しません。

代わりに、他の 3 つの解決策をお勧めします。

  • match_beginningetcを使用して手動で検索と分割を行い、
  • 文字で単純な分割を使用し、'/'必要に応じて文字列を再構成します。
  • たとえば、\\/文字を別の組み合わせ\\§(または処理したいテキストに表示される可能性が低い他の文字列) に置き換え、分割を行い、各部分文字列で逆の置換を行います (今回は「§」を「/」に置き換えるだけです)。 ')。

'/'inの適切な置換文字がある場合、最後のものはおそらく最速です"\\/"

于 2012-12-16T06:21:56.220 に答える
1

少しわかりにくい解決策を次に示します。

let rec split s = Scanf.sscanf s "%s@/%s@\n" (fun left right ->
  let llen = String.length left in
  let (left, escaped) = 
    if llen > 0 && left.[llen - 1] = '\\' then
      (String.sub left 0 (llen - 1), true) 
    else
      (left, false) in
  if right = "" then
    [left]
  else match split right with
    h :: t when escaped ->
      (left ^ "/" ^ h) :: t|
    ht ->
      left :: ht         
);;

そして出力:

# split "command/test \\/ escaped/";;
- : string list = ["command"; "test / escaped"]

少し不可解ですが、それでも機能します。

お役に立てれば!

于 2012-12-16T17:57:31.137 に答える
0

AFAIR、Str.regexpは構造をサポートしていません!

ただし、PCRE-OCamlライブラリは次のことを行います。

# #directory "+pcre";;
# #load "pcre.cma";;
# Pcre.split 
    ~rex:(Pcre.regexp ~flags:[`EXTENDED] "(?<!\\\\)/")
    "command/test \\/ escaped/"
  ;;
- : string list = ["command"; "test \\/ escaped"]

文字列エスケープを取り除きたい場合は、分割\/の結果を後処理するか、(より良い) matchを使用してそのリストを自分で作成する必要があります。

于 2012-12-17T17:34:15.063 に答える