http://qs321.pair.com?node_id=140143


in reply to Range of chars except one

I'm surprised no one's mentioned tr///; You'll still have to give it two ranges, but it works well.. It also has the added advantage (so far as i know) of being more efficient than s///;
You can give it the hex values, for example:
$string =~ tr/\x00-\x04\x07-\x09//d;

This'll get rid of the range \x00 through \x04, leave characters \x05 and \x06, and delete the range \x07 through \x09...
Of course.. it's too early for me to think straight, so the ranges given are bogus, but you get the idea..

-SynZero

Replies are listed 'Best First'.
Re: Re: Range of chars except one
by kjherron (Pilgrim) on Jan 20, 2002 at 11:29 UTC
    This can be made even simpler. Remember that if a character is listed in a tr/// searchlist more than once, only the first occurance is meaningful. This means you can do something like:
    $string =~ tr/\n\000-\037/\n/d;
    (Note I'm using octal here). This specifies that the newline character is replaced by itself, while everything else in that range is deleted.

    There are three advantages to this method: <NL>

  • It's (IMHO) cleaner and easier to read.
  • It's easier to modify, e.g. to exempt additional characters from being deleted.
  • It doesn't care what character is used for newline on the current platform. For example, I seem to remember that \n and \r have their meanings reversed on one platform (Macintosh?) because the platform standard is to use CR for line breaks. </NL>
      True i thought about tr/// too... but "a range of chars except one", could also be read "a range of chars PLUS one" (i like to reverse things up). tr/// also offer a complement modifier to it.
      So when i need to delete chars, it seems more simple to write the one i actually want to keep, preventing me to forget some:
      $_ = "123,Let's keep letters!\nAnd new lines..."
      tr/A-Za-z \n//cd;
      print;
      will print:
      Lets keep letters
      And new lines

      Creating that range could be easier...

      It's just my two cents.
      Freddo
Re: Re: Range of chars except one
by jlf (Scribe) on Jan 20, 2002 at 06:08 UTC
    I was thinking along the same lines, but the fact that Marcello is using variables rather than constants to define the range implies that his search ranges may vary. To use tr here with differing ranges, he must use eval. As we read in perlop,
    Because the transliteration table is built at compile time, neither the SEARCHLIST nor the REPLACEMENTLIST are subjected to double quote interpolation. That means that if you want to use variables, you must use an eval():
    eval "tr/$oldlist/$newlist/"; die $@ if $@; eval "tr/$oldlist/$newlist/, 1" or die $@;
    HTH,

    Josh