in reply to Search and replace in an array using data in hash

You're not using the fast lookup properties of a hash. Let $ipre be the regular expression you use for recognising ip addresses when you build %hosts. Make sure it captures the ip in $1. Reading INFILE line by line, and writing FQDN as we go,

{ local( *INFILE, *FQDN, $_); open INFILE, '< /path/to/longwood.pix' or die $!; open FQDN, '> /path/to/fqdn.pix' or die $!; while (<INFILE>) { s/$ipre/(exists($hosts{$1})?$hosts{$1}:$1)/eg; print FQDN $_ or die $!; } close FQDN or die $!; close INFILE or die $!; }

After Compline,
Zaxo

Replies are listed 'Best First'.
Re: Re: Search and replace in an array using data in hash
by monger (Friar) on Aug 08, 2003 at 18:13 UTC
    After looking at your suggestion, I'm not sure if it would work. So if you could, please explain. My questions follow.

    What I wanted to do was search on %hosts{$ip} and replace with %hosts{$a} where IP is the IP address of the host and $a is the hostname given by nslookup. I couldn't tell if that is exactly what your s///eg process was doing. Thanks, Monger
      Well, yes, there was viel magisches in that one line. Let's pull it apart.

      Because you said there could be more than one IP address per line Abigail-II, halley and Zaxo all understood they needed to find just IP addresses, maybe more than one, and then _maybe_ substitute a name. So they said:

      s/ <IP address pattern> / <magic> / g
      using the 'g' to match as many times as needed and using a special pattern to match only things that looked like IP addresses.

      For the special pattern Zaxo just said '$ipre' because there are a lot of REs you could use to match IP addresses. Abigail-II suggested you use the Regexp::Common module which has a predefined RE for that.

      So s///g will find each IP address in a line, save that matched string in $1, and then do the second part, the substitution. But we want to lookup the string and replace it only if it is _found_ in your hash.

      If you use the 'e' modifier on a s/// you are saying the second substitute part has _code_ in it. You can make decisions about exactly what to substitute. Zaxo used

      ( exists($hosts{$1}) ? $hosts{$1} : $1 )
      to make the decision very clear. He said that if the matched IP address (saved in $1) could be found in your hash (something existed in %hosts with the key $1) then we want to substitute the value in $hosts{$1}, otherwise we just want to use the original matched string (we don't have anything to substitute).

      What halley used was a shortcut way of saying the same thing:

      $hash{$1} || $1
      The || 'or' operator will use the first value if it is not false otherwise it will use the second value. If you try to lookup a value using a key when you haven't stored something in the hash using that key, Perl doesn't die but rather quietly says "I don't have anything here for that key." The value returned by $hash{'unbekannt'} is simply the 'undef' value. 'undef' is false so the above expression will throw away the first value and use the second value. So if the IP address is found in the hash we use '$hash{$1}' otherwise we use '$1'.

      Your code suggests that the keys of %hosts are ip numbers, and the values are a cache of the corresponding hostnames. That is the structure I wrote to. If %hosts is something different, please describe it and show the code which populates it.

      After Compline,
      Zaxo