2017-07-13 28 views
1

我有帶註釋屬性的字符串。您可以將它們視爲XML文檔字符串,但是可以使用自定義的註釋語法。用於檢索帶註釋字符串屬性的函數或宏

屬性字符串中的編碼如下:

#<atr_name>=<num_of_chars>:<atr_value>\n

其中

  • <atr_name>是屬性
  • <atr_value>的名稱是屬性的一個值
  • <num_of_chars><atr_value>的字符長度

即屬性名稱的前綴是#=後綴,再其次是表示在屬性值中的字符數數,再其次是:,再其次是屬性值本身,然後然後用換行符\n

下面是一個例子:

julia> string_with_attributes = """ 
some text 
... 
#name=6:Azamat 
... 
#year=4:2016 
... 
some other text 
""" 

現在我想編寫一個函數或宏,讓我爲撥打:

julia> string_with_attributes["name"] 
"Azamat" 

julia> string_with_attributes["year"] 
"2016" 

julia> 

有關如何做到這一點的任何想法?

回答

2

繼@Gnimuc答案,你可以讓自己的字符串宏 AKA 非標準字符串字面如果滿足您的需求,即:

julia> function attr_str(s::S)::Dict{S, S} where {S <: AbstractString} 
      d = Dict{S, S}() 
      for i in eachmatch(r"(?<=#)\b.*(?==).*(?=\n)", s) 
       push!(d, match(r".*(?==)", i.match).match => match(r"(?<=:).*", i.match).match) 
      end 
      push!(d, "string" => s) 
      return d 
     end 
attr_str (generic function with 1 method) 

julia> macro attr_str(s::AbstractString) 
      :(attr_str($s)) 
     end 
@attr_str (macro with 1 method) 

julia> attr""" 
      some text 
      dgdfg:dgdf=ert 
      #name=6:Azamat 
      all34)%(*)#:DG:Ko_=ddhaogj;ldg 
      #year=4:2016 
      #dkgjdlkdag:dfgdfgd 
      some other text 
      """ 
Dict{String,String} with 3 entries: 
    "name" => "Azamat" 
    "string" => "some text\ndgdfg:dgdf=ert\n#name=6:Azamat\nall34)%(*)#:DG:Ko_=ddhaogj;ldg\n#year=4:2016\n#dkgjdlkdag:dfgdfgd\nsome other text\n" 
    "year" => "2016" 

julia> 
2

似乎是正則表達式工作:

julia> string_with_attributes = """ 
     some text 
     dgdfg:dgdf=ert 
     #name=6:Azamat 
     all34)%(*)#:DG:Ko_=ddhaogj;ldg 
     #year=4:2016 
     #dkgjdlkdag:dfgdfgd 
     some other text 
     """ 
"some text\ndgdfg:dgdf=ert\n#name=6:Azamat\nall34)%(*)#:DG:Ko_=ddhaogj;ldg\n#year=4:2016\n#dkgjdlkdag:dfgdfgd\nsome other text\n" 
julia> s = Dict() 
Dict{Any,Any} with 0 entries 

julia> for i in eachmatch(r"(?<=#)\b.*(?==).*(?=\n)", string_with_attributes) 
     push!(s, match(r".*(?==)", i.match).match => match(r"(?<=:).*", i.match).match) 
     end 

julia> s 
Dict{Any,Any} with 2 entries: 
    "name" => "Azamat" 
    "year" => "2016" 
+0

看到我的答案。謝謝。 – aberdysh

+1

@aberdysh棘手,但我認爲擴展'Base.getindex'在這裏有點矯枉過正,這個功能對你至關重要嗎?如果你想匹配另一種模式,你會怎麼做? – Gnimuc

0

所以,原來我需要的是從Indexing接口擴展Base.getindex方法。

這裏是我最後做的解決方案:

julia> 
function Base.getindex(object::S, attribute::AbstractString) where {S <: AbstractString} 
    m = match(Regex("#$(attribute)=(\\d*):(.*)\n"), object) 
    (typeof(m) == Void) && error("$(object) has no attribute with the name $(attribute)") 
    return m.captures[end]::SubString{S} 
end 


julia> string_with_attributes = """ 
    some text 
    dgdfg:dgdf=ert 
    #name=6:Azamat 
    all34)%(*)#:DG:Ko_=ddhaogj;ldg 
    #year=4:2016 
    #dkgjdlkdag:dfgdfgd 
    some other text 
    """ 

julia> string_with_attributes["name"] 
"Azamat" 

julia> string_with_attributes["year"] 
"2016"