Replace a text in perl - perl

I am trying to find a particular string in file and want to replace that string with another string. Then i want to replace this string in the file also. I am using following code:
open(FILEB,"+<File B (2).txt");
$hostNameA="Any string\n";
foreach $lineB(FILEB)
{
seek(FILEB,-length($lineB),1);
$lineB=~s/$hostNameB/$hostNameA/;
print FILEB $lineB;
}
Basically, my query is how to replace hostNameB ith hostNameA in FileB....

If you are working on linux, there is no need to even open a file and no need to create backup file. Following script should work -
#!/usr/bin/perl
#Commandline
my $command = "sed -i 's/FOO/BAR/g' /mydir/myfile.txt";
#Execute Command
`$command`;
Above script will replace all occurrences of string 'FOO' with 'BAR' in myfile.txt

Write file with same handle will destroy original file.
open IN, '<', 'path_to_file' or die $!
open OUT, '>', 'path_to_replaced_file' or die $!;
while (my $line = <IN>) {
$line =~ s/something/tosomething/g;
print OUT $line;
}
close OUT;
close IN;
# if you wish, backup old file, and rename new file

How about this
$ perl -pi.bak -e 's/hostNameB/hostNameA/g' "File B (2).txt"
read the file from "File B (2).txt" and then edit it with regex 's/hostNameB/hostNamea/g'
And back up the original file.

Related

Replace a string in file

My file is like this
DIV=25
FACILITY=11111
and I want to use Perl to replace DIV=25 into DIV=30. Below is my script to do it, but the output of the file is DIV=3030
open( IN_IOE, $FILE_NAME ) || die "Cannot open file";
my #line_ioe = <IN_IOE>;
close(IN_IOE);
chomp #line_ioe;
foreach $_ ( #line_ioe ) {
s/DIV=/DIV=30/
}
open( OUT, ">test.txt" );
foreach $_ (#line_ioe) {
print OUT "$_ \n";
}
close(OUT);
The output of my file is
DIV=3030
FACILITY=11111
Can anyone please show me how to replace that line in file with Perl, and point out where I was wrong.
You can do that in one line of Perl at the command line:
perl -pi -e 's/DIV=25/DIV=30/' file.txt
if you have multiple lines with different numeric numbers (i.e. DIV=25, DIV =31, DIV=21) you could do following.
s/DIV=\d+/DIV=25/g
here \d is to replace any digits and 'g' to perform this globally.
The code you show certainly didn't change DIV=30 into DIV=3030. It didn't do anything at all because you have opened your output file for input
This line
open( OUT, "<test.txt");
should look like this
open OUT, '>', 'test.txt' or die $!;
Also, if you want to replace DIV=30 with DIV=25 then you need to write that. I think it's clear that the substitution
s/DIV=/DIV=25/
will change DIV=30 into DIV=2530. Use this instead
s/DIV=30/DIV=25/

Perl Get the web content then writing it as a text file

I'm trying to create a script which get from the website a log file(content) then inputting it to a text file, but I am having errors if use strict is present:
Can't use string ("/home/User/Downloads/text") as a symbol ref while "strict refs" in use at ./scriptname line 92.
Also by removing the use strict: I get another error which is:
File name too long at ./scriptname line 91.
I tried the Perl: Read web text file and "open" it
But, it did not work for me. Plus I am a newbie at Perl and confuse of the Perl syntax.
Are there any suggestions or advices available?
Note: The code does it greps the entire line with the RoomOutProcessTT present and display it together with how many times it appears.
Here is the code.
my $FOutput = get "http://website/Logs/Log_number.ini";
my $FInput = "/home/User/Downloads/text";
open $FInput, '<', $FOutput or die "could not open $FInput: $!";
my $ctr;
my #results;
my #words = <$FInput>;
#results = grep /RoomOutProcessTT/, #words;
print "#results\n";
close $FInput;
open $FInput, '<', $FOutput or die "could not open $FInput: $!";
while(<$FInput>){
$ctr = grep /RoomOutProcessTT/, split ' ' , $_;
$ctr += $ctr;
}
print "RoomOutProcessTT Count: $ctr\n";
close $FInput;
The first argument to open is the filehandle name, not the actual name of the file. That comes later in the open function.
Change your code to:
my $FOutput = get "http://website/Logs/Log_number.ini"; # your content should be stored in this
# variable, you need to write data to your output file.
my $FInput = "/home/User/Downloads/text";
open OUTPUT_FILEHANDLE, '>', $FInput or die "could not open $FInput: $!"; # give a name to the file
# handle, then supply the file name itself after the mode specifier.
# You want to WRITE data to this file, open it with '>'
my $ctr;
my #results;
my #words = split(/(\r|\n)/, $FOutput); # create an array of words from the content from the logfile
# I'm not 100% sure this will work, but the intent is to show
# an array of 'lines' corresponding to the data
# here, you want to print the results of your grep to the output file
#results = grep /RoomOutProcessTT/, #words;
print OUTPUT_FILEHANDLE "#results\n"; # print to your output file
# close the output file here, since you re-open it in the next few lines.
close OUTPUT_FILEHANDLE;
# not sure why you're re-opening the file here... but that's up to your design I suppose
open INPUT_FILEHANDLE, '<', $FInput or die "could not open $FInput: $!"; # open it for read
while(<INPUT_FILEHANDLE>){
$ctr = grep /RoomOutProcessTT/, split ' ' , $_;
$ctr += $ctr;
}
print "RoomOutProcessTT Count: $ctr\n"; # print to stdout
close INPUT_FILEHANDLE; # close your file handle
I might suggest switching the terms you use to identify "input and output", as it's somewhat confusing. The input in this case is actually the file you pull from the web, output being your text file. At least that's how I interpret it. You may want to address that in your final design.

How do I copy a CSV file, but skip the first line?

I want to write a script that takes a CSV file, deletes its first row and creates a new output csv file.
This is my code:
use Text::CSV_XS;
use strict;
use warnings;
my $csv = Text::CSV_XS->new({sep_char => ','});
my $file = $ARGV[0];
open(my $data, '<', $file) or die "Could not open '$file'\n";
my $csvout = Text::CSV_XS->new({binary => 1, eol => $/});
open my $OUTPUT, '>', "file.csv" or die "Can't able to open file.csv\n";
my $tmp = 0;
while (my $line = <$data>) {
# if ($tmp==0)
# {
# $tmp=1;
# next;
# }
chomp $line;
if ($csv->parse($line)) {
my #fields = $csv->fields();
$csvout->print($OUTPUT, \#fields);
} else {
warn "Line could not be parsed: $line\n";
}
}
On the perl command line I write: c:\test.pl csv.csv and it doesn't create the file.csv output, but when I double click the script it creates a blank CSV file. What am I doing wrong?
Your program isn't ideally written, but I can't tell why it doesn't work if you pass the CSV file on the command line as you have described. Do you get the errors Could not open 'csv.csv' or Can't able to open file.csv? If not then the file must be created in your current directory. Perhaps you are looking in the wrong place?
If all you need to do is to drop the first line then there is no need to use a module to process the CSV data - you can handle it as a simple text file.
If the file is specified on the command line, as in c:\test.pl csv.csv, you can read from it without explicitly opening it using the <> operator.
This program reads the lines from the input file and prints them to the output only if the line counter (the $. variable) isn't equal to one).
use strict;
use warnings;
open my $out, '>', 'file.csv' or die $!;
while (my $line = <>) {
print $out $line unless $. == 1;
}
Yhm.. you don't need any modules for this task, since CSV ( comma separated value ) are simply text files - just open file, and iterate over its lines ( write to output all lines except particular number, e.g. first ). Such task ( skip first line ) is so simple, that it would be probably better to do it with command line one-liner than a dedicated script.
quick search - see e.g. this link for an example, there are numerous tutorials about perl input/output operations
http://learn.perl.org/examples/read_write_file.html
PS. Perl scripts ( programs ) usually are not "compiled" into binary file - they are of course "compiled", but, uhm, on the fly - that's why /usr/bin/perl is called rather "interpreter" than "compiler" like gcc or g++. I guess what you're looking for is some editor with syntax highlighting and other development goods - you probably could try Eclipse with perl plugin for that ( cross platform ).
http://www.eclipse.org/downloads/
http://www.epic-ide.org/download.php/
this
user#localhost:~$ cat blabla.csv | perl -ne 'print $_ if $x++; '
skips first line ( prints out only if variable incremented AFTER each use of it is more than zero )
You are missing your first (and only) argument due to Windows.
I think this question will help you: #ARGV is empty using ActivePerl in Windows 7

How to get filename of a opened file?

I have this simple script that I'm working on. I must admit, I'm totally new to PERL and kinda stuck with this stupid problem.
open(IN, "<def/t.html") or die();
while(<IN>) {
chomp;
if($_ =~ m/FF0000/) {
print "\n".$_."\n";
}
}
So... I opened the t.html and found the given string in the file. Output was ok, but I need also filename of a file in which string was found, to be printed. I really don't know how to return this, and I need it right after the $_. Thanks for the help in advance.
Simply save the file name in a variable before you open it, then go from there:
my $filename = 'def/t.html';
open( IN, '<', $filename ) or die $!;
...
print "\n$filename: " . $_ . "\n";
Notice that the above uses the 3-arg form of open(), which is safer.
(Also, the language is "Perl", not "PERL".)
That is a strange idea, but you can if you want:
$ cat 1.pl
#somewhere in the code
open(F, "f.txt");
my $f = fileno(F);
#here you want to find the filename
open(FILENAME, "ls -l /proc/$$/fd/$f|");
my #fn = split(/\s+/, <FILENAME>);
print $fn[$#fn],"\n";
$ perl 1.pl
/home/ic/f.txt
Here you know only the filedescriptor and find the filename using it.
You can also write it much shorter with readlink:
open(F, "f.txt");
my $f = fileno(F);
#here you want to find the filename
print readlink("/proc/$$/fd/$f"), "\n";
I must note that the file can be already deleted (but it exists still if it is open).

perl + append text between two lines in file

I need to edit file , the main issue is to append text between two known lines in the file
for example I need to append the following text
a b c d e f
1 2 3 4 5 6
bla bla
Between the first_line and the second_line
first_line=")"
second_line="NIC Hr_Nic ("
remark: first_line and second_line argument can get any line or string
How to do this by perl ? ( i write bash script and I need to insert the perl syntax in my script)
lidia
You could read the file in as a single string and then use a regular expression to do the search and replace:
use strict;
use warnings;
# Slurp file myfile.txt into a single string
open(FILE,"myfile.txt") || die "Can't open file: $!";
undef $/;
my $file = <FILE>;
# Set strings to find and insert
my $first_line = ")";
my $second_line = "NIC Hr_Nic (";
my $insert = "hello world";
# Insert our text
$file =~ s/\Q$first_line\E\n\Q$second_line\E/$first_line\n$insert\n$second_line/;
# Write output to output.txt
open(OUTPUT,">output.txt") || die "Can't open file: $!";
print OUTPUT $file;
close(OUTPUT);
By unsetting $/ we put Perl into "slurp mode" and so can easily read the whole file into $file.
We use the s/// operator to do a search and replace using our two search lines as a pattern.
The \Q and \E tell Perl to escape the strings between them, i.e. to ignore any special characters that happen to be in $first_line or $second_line.
You could always write the output over the original file if desired.
The problem as you state it is not solvable using the -i command line option since this option processes a file one line at a time; to insert text between two specific lines you'll need to know about two lines at once.
Well to concenate strings you do
my $text = $first_line . $second_line;
or
my $text = $first_line;
$text .= $second_line;
I'm not sure if I understand your question correctly. A "before and after" example of the file content would, I think, be easier. Anyhow, Here's my take on it, using splice instead of a regular expression. We must of course know the line numbers for this to work.
Load the file into an array:
my #lines;
open F, '<', 'filename' or die $!;
push #lines, $_ for <F>;
close F;
Insert the stuff (see perldoc -f splice):
splice #lines, 1, 0, ('stuff');
..and you're done. All you need to do now is save the array again:
open F, '>', 'filename' or die $!;
print F #lines;
close F;