String 以Rebol或Red格式搜索字符串

String 以Rebol或Red格式搜索字符串,string,rebol,rebol2,red,String,Rebol,Rebol2,Red,我对搜索大量长字符串感兴趣,尝试在rebol中创建一个类似sed的实用程序作为学习练习。作为第一步,我决定搜索一个角色: >> STR: "abcdefghijklmopqrz" >> pos: index? find STR "z" == 18 >> pos == 18 太好了!让我们找点别的 >> pos: index? find STR "n" ** Script Error: index? expected series argume

我对搜索大量长字符串感兴趣,尝试在rebol中创建一个类似sed的实用程序作为学习练习。作为第一步,我决定搜索一个角色:

>> STR: "abcdefghijklmopqrz"

>> pos: index? find STR "z"
== 18

>> pos
== 18
太好了!让我们找点别的

>> pos: index? find STR "n"
** Script Error: index? expected series argument of type: series port
** Where: halt-view
** Near: pos: index? find STR "n"

>> pos
== 18
什么-(

是的,我搜索的字符串中没有“n”。但是解释器爆炸而不是做一些合理的事情,比如在pos中返回一个可测试的“null”字符有什么好处呢

我被告知我应该这样做:

>> if found? find STR "z" [pos: index? find STR "z"]
== 18

>> if found? find STR "n" [pos: index? find STR "n"]
== none

>> pos
== 18
>> if found? find STR "z" [pos: index? find STR "z"]
== 18

>> if found? find STR "n" [pos: index? find STR "n"]
== none

>> pos
== 18
真的吗?我必须搜索字符串两次;第一次只是为了确保再次搜索“安全”

所以我有一个三部分的问题:

  • 一个向导将如何实现我的搜索功能?我想有一个比这个更好的方法

  • Red会改变这一点吗?理想情况下,我认为find应该返回一个有效的字符串位置,或者如果它到达字符串的末尾,则返回NULL(我可以假定是NULL分隔的吗?)。NULL为FALSE,这样可以设置一个非常简单的if测试

  • 一旦我有了一个有效的索引,什么是进行替换的最有效的CPU方法?Rebol中似乎有很多选择(一件好事),以至于可能会陷入选择或陷入次优选择

  • 我被告知我应该这样做:

    >> if found? find STR "z" [pos: index? find STR "z"]
    == 18
    
    >> if found? find STR "n" [pos: index? find STR "n"]
    == none
    
    >> pos
    == 18
    
    >> if found? find STR "z" [pos: index? find STR "z"]
    == 18
    
    >> if found? find STR "n" [pos: index? find STR "n"]
    == none
    
    >> pos
    == 18
    
    真的吗?我必须搜索字符串两次;第一次只是为了确保再次搜索“安全”

    当然,您不必搜索字符串两次。但是
    索引?
    (可能是将来的名称,因为它不返回yes/no:
    索引的
    )在给定NONE!输入时不会返回NONE!值。它假定调用者想要返回整数位置,如果不能返回,则会引发错误

    向导如何实现我的搜索功能? 要消除双重搜索,可以使用短路评估

    >> all [pos: find STR "z" pos: index? pos]
    == 18
    
    >> pos
    == 18
    
    >> all [pos: find STR "n" pos: index? pos]
    == none
    
    >> pos
    == none
    
    但请注意,如果不引入第二个变量,您将覆盖以前的
    pos
    。假设您调用变量
    index
    ,而pos是临时变量:

    >> all [pos: find STR "z" index: index? pos]
    == 18
    
    >> index
    == 18
    
    >> all [pos: find STR "n" index: index? pos]
    == none
    
    >> index
    == 18
    
    在表达式中间的任意点抛出集合词的能力非常强大,这就是为什么像多重初始化(
    a:b:c:0
    )这样的东西不是语言的特殊功能,而是不属于计算器模型的东西

    瑞德会改变这一切吗?
    index?
    (cough
    index of
    )返回一个NONE!值(如果给定一个NONE!输入)的好处不太可能超过它如此宽容所带来的问题。这始终是一种平衡

    请注意,FIND的行为确实如您所期望的那样。FIND?只是一种语法上的便利,它可以将找到的位置转换为真值,将NONE!转换为假值。它相当于调用true?(但在阅读时只需要稍微熟练一点).没有必要在“如果”或“除非”或“任一”的情况下使用它,因为他们会将“无”结果视为“假”,而将任何位置视为“真”

    一旦我有了一个有效的索引,最有效的CPU替换方法是什么? 最快的可能是挂在位置上,说
    change pos#“x”
    (尽管是内部的“位置”)是通过索引加序列实现的,而不是独立的指针。因此,在微优化世界中,优势并不是那么显著,在微优化世界中,我们计算的是偏移量的增加……)

    至于使用索引的操作:我会说选择您最喜欢的方式,然后进行微优化

    我个人并不认为
    STR/:index:#“x”
    看起来那么好,但它是最简洁的字符

    STR/(index):#“x”
    做了同样的事情,在我看来看起来更好。但代价是源代码结构有点膨胀。这是一个SET-PATH!系列,包含一个PAREN!系列,后跟一个CHAR!…所有这些都嵌入到保存代码的原始系列“vector”中。在引擎盖下会出现局部性问题

    看起来很幼稚的POKE可能是最快的。
    POKE STR index#“x”
    。它可能看起来像“4个元素而不是2个”,但路径案例中的“2个元素”只是一种幻觉

    在Rebol中,猜测总是有点困难,因此您必须收集数据。您可以运行一些重复的迭代测试来找出答案。要对代码块计时,请参阅内置的
    delta time


    红色的编译表单应该是等效的,但如果以某种方式结束了对它的解释,您可能会有与Rebol类似的时间安排。

    毫不奇怪,HostileFork答案完美地涵盖了所有内容!+1

    我只是想为我经常使用的第1点添加一个替代解决方案:

    >> attempt [index? find STR "z"]   
    == 18
    
    >> attempt [index? find STR "n"] 
    == none
    

    Rebol 2和Rebol 3的在线文档

    以红色/Rebol搜索字符串非常简单方便。关于您遇到的问题,让我为您解包详细信息:

    首先,解释器以错误消息的形式向您提供了一个很好的错误提示:
    index?类型为:series port
    的预期系列参数。这意味着您在错误的数据类型上使用了
    index?
    。这是怎么发生的?原因很简单,因为函数在电子搜索失败:

    >> str: "abcdefghijklmopqrz"
    >> find str "o"
    == "pqrz"
    >> type? find str "o"
    == string!
    
    >> find str "n"
    == none
    >> type? find str "n"
    == none!
    
    因此,直接对
    find
    的结果使用
    index?
    是不安全的,除非您知道搜索不会失败。如果您仍然需要提取索引信息,安全的方法是首先测试
    find
    的结果:

    >> all [pos: find str "o" index? pos]
    == 14
    >> all [pos: find str "n" index? pos]
    == none
    >> if pos: find str "o" [print index? pos]
    == 14
    >> print either pos: find str "n" [index? pos][-1]
    == -1
    
    根据您的需要,这些只是实现它的安全方法的示例。请注意,
    none
    if
    中的条件测试中充当
    false
    ,因此在这种情况下使用
    found?
    是多余的

    现在让我们来解释一下给你们带来困惑的核心问题。 Rebol语言有一个基本概念,称为
    >> a: next s
    == "ello"
    >> b: skip s 3
    == "lo"
    >> s: at s 5
    == "o"
    >> reduce [a b s]
    == ["ello" "lo" "o"]
    >> reduce [index? a index? b index? s]
    == [2 4 5]
    
    >> STR: "abcdefghijklmopqrz"
    >> find STR "z"
    == "z"
    >> find STR "n"
    == none
    
    >> pos: find STR "o"
    >> if pos [print "found"]
    found
    >> print ["sub-string from `o`:" pos]
    sub-string from `o`: opqrz
    >> length? pos
    == 5
    >> index? pos
    == 14
    >> back pos
    == "mopqrz"
    >> skip pos 4
    == "z"
    
    >> pos: find STR "n"
    >> print either pos ["found"]["not found"]
    not found
    >> print either pos [index? pos][-1]
    -1
    
    >> s: "The score is 1:2 after 5 minutes"
    >> if pos: find/tail s "score is " [print copy/part pos find pos " "]
    1:2