open (HAN1, "<test1.txt") || die "not existing!";
open (HAN2, "test2.txt") || die "not existing!";
s/nameserver/nameserver/g;
print HAN2 $_;
}
close(HAN1);
close(HAN2);
~
test1.txt
nameserver 10.66.80.10
nameserver 10.66.80.11
nameserver 10.66.80.11
test2.txt
search test.com
nameserver 99.66.80.10
nameserver 98.66.80.11
nameserver 98.66.80.11
After running the script test2.txt its removing other string content.
nameserver 10.66.80.10
nameserver 10.66.80.11
nameserver 10.66.80.11
But want the result test2.txt
search test.com
nameserver 10.66.80.10
nameserver 10.66.80.11
nameserver 10.66.80.11
Try this ,
use strict;
use warnings;
use Data::Dumper;
open (HAN1, "<test1.txt") || die "not existing!";
open (HAN2, "<test2.txt") || die "not existing!";
my $current;
my #arr1 = <HAN1>;
foreach $current (<HAN2>) {
unless ($current =~ /nameserver/) {
print $current;
next;
}
foreach (#arr1) {
my($first,$second) = split (' ',$_);
$current =~ s/^(nameserver\s+).+/$_/g;
chomp($current);
print $current;
last;
}
shift #arr1;
}
close(HAN1);
close(HAN2);
Related
I have a function like this:
open my $pipe, "-|", '/usr/bin/externalcmd | /usr/bin/awk \'{print $2" "$4}\''
|| die "can't fork command: $!";
while (<$pipe>) {
my ($if, $ip) = split;
my $file = "/some/file/$if";
open (FILE, ">$file") || die "can't open $file for $ip: $!";
# ...
close(FILE);
}
close ($pipe);
It fails on open with the following error:
Insecure dependency in open while running with -T switch at line 1383, <$pipe> line 1.
How can I fix this?
The answer was to "launder" the $if variable through a regex match like this:
# e.g., only "word" characters
if ($if =~ /^([-\#\w.]+)\z/) {
$if = $1;
} else {
die "Bad data in '$if'";
}
Then proceed as before.
I have the below file
file1:
abc def host 123 host 869 host
I wrote below script to count the occurrence of a "host" keyword in each line.
I tried all the ways(refer the ones which are commented) still it does not seem to work. sed command worked in command line but not inside the perl script
#!/usr/bin/perl
open(SOURCE,"</home/amp/surevy01/file1");
open(DESTINATION,"</home/amp/surevy01/file2");
while(my $line = <SOURCE>)
{
while(my $line1 = <DESTINATION>)
{
#chomp($line);
#chomp($line1);
if ($line =~ "host")
{
#my $count = grep {host} $line;
#my $count = `sed -i {s/host/host\n/g} $line1 | grep -c {host}`;
#my $count = `perl -pi -e 's/host/host\n/g' $line1 | grep -c host`;
#my $count grep ("host" ,$line);
print "$count";
print "match found \n";
next;
}
else
{
print "match not found \n";
exit;
}
}
}
I'm a beginner to perl. Looking for your valuable suggestions
Your own solution will match instances like hostages and Shostakovich
grep is the canonical way to count elements of a list, and split will turn your line into a list of words, giving
my $count = grep { $_ eq 'host' } split ' ', $line
I don't know why you're looping through two files in your example, but you can use the /g (global) flag:
my $line = "abc def host 123 host 869 host";
my $x = 0;
while ($line =~ /host/g){
$x++;
}
print "$x\n"; # 3
When you run a regex with /g in scalar context (as is the conditional in the while statement), it will keep track of the location of the last match and restart from there. Therefore, /host/g in a loop as above will find each occurence of host. You can also use the /g in list contexts:
my $line = "abc def host 123 host 869 host";
my #matches = $contents =~ /host/g;
print scalar #matches; # 3 again
In this case, #matches will contain all matches of the regexp against the string, which will be ('host', 'host', 'host') since the query is a simple string. Then, scalar(#matches) will yield the length of the list.
This produces the number of instances of host in $line:
my $count = () = $line =~ /host/g;
But that also matches hosting. To avoid that, the following will probably do the trick:
my $count = () = $line =~ /\bhost\b/g;
=()= this is called Perl secret Goatse operator. More info
I'm trying to convert IP's to hostnames via file using perl (without using built in Socket function).
My file looks like this:
192.168.1.1 firewall
192.168.2.4 wifi
192.168.3.10 switch
My code:
use strict;
use warnings;
my $input_dns_file='./file';
our %ip2host_hash;
sub read_dns_file()
{
open(DNS_FILE,'<',$input_dns_file) or die;
while ( my $line=<DNS_FILE> ){
my ($ip,$hostname) = split(/\s+/,$line,2);
$ip2host_hash{$ip} = $hostname;
}
The problem is that the hash always return the first line of the file. How do I fill the hash %ip2host so it can return every hostname when I enter the IP address?
I think what you are looking for is a script to extract a hostname from a list (on file), given the IP. This is simple. Here's a one-liner:
perl -wle '
$ip = shift;
%list = map split,<>;
print $list{$ip} || "$ip not found";
' 192.168.2.24 list_of_ips
-l will chomp the input and add a newline to print (for convenience). map will just split each element in the input list, so it fits with a hash structure. The last statement will print the hostname, if it is found, or an error if not.
Here's a script:
use strict;
use warnings;
my $ip = shift;
my $file = "list_of_ips";
open my $fh, '<', $file or die $!;
my %list = map split, <$fh>;
print $list{$ip} || "$ip not found\n";
What you may consider is using a short circuit, to return as soon as a match is found. This will be better from a performance point of view, especially with large input files.
while (<$fh>) {
my ($num, $host) = split;
if ($num eq $ip) {
print $host;
last;
}
}
Here is what im trying to achieve.
I have a perl script that looks into a group of directly parse the files it finds and locates a specific string. If it finds the specific string, it ignores it, if it finds the first part of the string, but the second part doesnt match, it writes it out to a log file.
The part im stuck with, is how to read the entire file in, and look to see if the string exists in the entire file.
Some background, im trying to write a script that will read cisco rancid files, and looks for the sys logging details. These are stored in the config as such
logging x.x.x.x
where x.x.x.x is the syslog IP address.
Currently, i can read in the file, check it line by line, and see if the file contains logging x.x.x.x, if it does, it ignores it.
If it contains logging y.y.y.y (where y is an IP different to what it should be), it will write out to a log file, that the logging is setup, but incorrectly configured. But i cant for the life of me work out how to get it to read the entire file, and if logging x.x.x.x or even logging y.y.y.y doesnt exist to write out that it is not configured.
script is below
#!/usr/bin/perl
use strict;
use warnings;
#Syslog Checker.... V0.0.1
##Config Items
my $basedir = "/home/srelf/Documents/Projects/perl/Configs";
my #verdir = qw(sw_a);
my $fulldir;
my $configs;
my $loghost = "x.x.x.x";
my $combidir;
use POSIX qw(strftime);
$now_string = strftime "%a%b%e%Y", gmtime;
open FILE, ">>Configchecker.$now_string.txt" or die $!;
print FILE "### Logging Host Settings ###\n";
close FILE;
foreach $combidir (#verdir) {
$fulldir = "$basedir/$combidir";
opendir( DIR, $fulldir );
my #files = grep { $_ ne '.' && $_ ne '..' } readdir DIR;
closedir(DIR);
while ( #files > 0 ) {
$configs = pop #files;
# print "$fulldir/$configs\n"; # used for debug shows current file with full path.
open FH, "$fulldir/$configs" or die $!;
#dataarry = <FH>;
foreach my $line (#dataarry) {
# Start an if statement, the condition of which is
# "If this particular line contains logging + IP address."
if ( $line =~ m/logging \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/i ) {
#then if the line located above contains logging and the log host ignore it
if ( $line =~ m/logging $loghost/i ) {
}
# if the above line contains an ip but it is not the correct ip do the below.
elsif ( $line =~
m/logging \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/i )
{
open FILE, ">>Configchecker.$now_string.txt" or die $!;
print FILE "$configs\n";
print FILE
"Logging for this device is set, but pointing at the wrong host: $line\n";
close FILE;
} # End the if condition here.
}
}
} # End the foreach loop here;
open FILE, ">>Configchecker.$now_string.txt" or die $!;
print FILE "### NTP Settings Check ###\n";
close FILE;
}
Thanks in advance for any help.
Im very new to perl, this is my first shot.
Steve.
foreach my $configs (#files)
{
my $CONFIGURED=0;
open FH, "$fulldir/$configs" or die $!;
while (<FH>)
{
if ($_ =~ m/logging/)
{
$CONFIGURED++;
}
if ($_ =~ m/logging \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/i and $_ !~ m/logging $loghost/i)
{
print "Logging for this device is set, but pointing at the wrong host: $_\n";
}
}
if ($CONFIGURED == 0)
{
print "NOT CONFIGURED $configs\n";
}
}
I want to compare each user in the passwd file with his entry in the shadow file, and print out the whole line of the passwd file if the entry in the shadow file matches 999999. What is the easiest way in Perl to do this? Or I suppose I could awk the values out of one file and match in the other file? What is the best way of doing this?
awk -F":" 'FNR==NR&&$5=="99999"{user[$1];next}($1 in user)' /etc/shadow /etc/passwd
change FNR==NR&&$5=="99999" to FNR==NR&&$5=="99999"&&$2!="!!" if you want to exclude lines with "!!"
#! /usr/bin/perl
use warnings;
use strict;
sub read_passwd {
open my $fh, "<", "/etc/passwd" or die "$0: open: $!";
my %passwd;
while (<$fh>) {
next unless /^([^:]+)/;
$passwd{$1} = $_;
}
\%passwd;
}
my $passwd = read_passwd;
open my $fh, "<", "/etc/shadow" or die "$0: open: $!";
while (<$fh>) {
my($user,$maxage) = (split /:/)[0,4];
next unless $maxage eq 99999;
if ($passwd->{$user}) {
print $passwd->{$user};
}
else {
warn "$0: no passwd entry for '$user'";
}
}
sudo perl -F: -lane '(1..eof)?($_{$F[0]}=$_):/999999/&&($_=$_{$F[0]})&&print' /etc/passwd /etc/shadow
You could use AnyData::Format::Password:
#!/usr/bin/perl
use strict; use warnings;
use AnyData;
my $passwd = adTie(Passwd => 'passwd' );
my $shadow = adTie(Passwd => 'shadow' );
for my $user (keys %$shadow) {
if ( $user->{fullname} and $user->{fullname} eq '999999' ) {
print $passwd->{$user->{username}}{fullname}, "\n";
}
}
Output:
...
Privilege-separated SSH
RPC Service User
Anonymous NFS User
HAL daemon
Or:
for my $user (keys %$shadow) {
if ( $user->{fullname} and $user->{fullname} eq '999999' ) {
my #values = map { defined $_ ? $_ : '' }
#{ $passwd->{$user->{username}} }{#fields};
print join(':', #values), "\n";
}
}