Loading ...
Sorry, an error occurred while loading the content.

47652Re: Preserve case during search & replace?

Expand Messages
  • gumnos (Tim Chase)
    Feb 10, 2004
    • 0 Attachment
      > Basically, I'd like to replace (e.g.) "apple" with "banana"
      > everywhere in a block of text, but if "apple" happens to be
      > capitalized, it should be replaced with "Banana". In other
      > words, I'd like a handy way of doing
      >
      > :s/Apple/Banana/g
      > :s/apple/banana/g
      >
      > (assuming noignorecase) with one command.

      I've toyed with this idea before, even asking the list at one point.
      However, you hit cases (including your own example) where the search-regex
      and the replacement don't line up correctly. eg.

      :s/ApplE/FOO/g

      What's the replacement "FOO"? would it be "BanaNa" or would it be
      "BananA" (is that a "make the 5th letter uppercase", or is it a "make the
      last letter uppercase"). It gets worse, if you use camel-case:

      :s/HelloWorld/SomeText/g
      :s/helloworld/sometext/g
      :s/helloWorld/someText/g

      is likely what you want, but with the below suggestion, you end up with
      something more like

      :s/HelloWorld/SometExt/g
      :s/helloworld/sometext/g
      :s/helloWorld/sometExt/g

      It really does take some sort of script logic to perform, where the script
      clarifies these peculiar cases. I think there's a simple script (that
      came out when I asked, or perhaps before) that handles the first N
      characters of the replacement text, where N is the length of the matched
      expression. I don't know if its author is around somewhere, or if it's be
      enhanced any.

      It would be of the form (wrapped for email, but should be on all one
      line):

      :%s/apple\c/\=CaseSubstitute(submatch(0),
      "desired_replacement_text")/g

      where CaseSubstitute(searchString, replacementString) does something like
      the pseudo-code

      outputString = ""
      for index = 1 to strlen(searchString)
      if isUpper(searchString[i]) outputString =
      outputString . upper(replacementString[i])
      else outputString = outputString .
      lower(replacementString[i])
      next
      append any additional bit of replacementString that
      doesn't have a corresponding letter in the match
      string
      return outputString

      for the isUpper(), you could use
      match(searchString[i], "\\u")

      for upper(), you could use
      substitute(replacementString[i], ".", "\\u&", "")

      for lower(), you could use
      substitute(replacementString[i], ".", "\\l&", "")

      (if OE bunged those replacements by attempting to turn them into UNC
      names, that's back-slash, back-slash, followed by either a "u" or
      lowercase "L", followed by an ampersand)

      You might also prefer to use [:upper:] as a character class rather than
      "\u", which may handle foreign character sets a little more gracefully,
      and the number of backslashes may need to be escaped properly--my guess
      was for only two, but I'm frequently unlucky on my first guess at escaping
      here :)

      Hope this sets you out in a helpful direction,

      -tim
    • Show all 22 messages in this topic