for example I have the following code
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
The lines start with ! sign which is comment lines in fortran. I want those comment lines have the same indent as their previous line indent.
That is I want this format
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
I want to do this in notepad++ using regex. But if there are better choice feel free to answer.
Here is what I have tried: replace ^(\s*)(.*?\r\n)\s*\! as $1$2$1!. However it produce
Module MPI
Use MPI
!
! MPI info
If (true) Then
Print *, ''
! empty line 1
! empty line 2
End If
Integer ithread, nthread, ierr
End Module MPI
There is still two lines not right. It seems that though the pattern ^(\s*)(.*?\r\n)\s*\! matches this line, however, it just skip it for the regex engine already matched previous lines.
My question is how to solve this indent problem with regex?
Using the search text ^( +)(.*\R)(!) and the replace text \1\2\1\3 then clicking on "Replace all" twice does what is wanted on the sample text. I cannot see a way of doing this in one pass.
The expression looks for a line with leading spaces followed by a line starting with a !. The capture groups are the leading spaces in \1, the rest of that line including the newline in \2 and the leading ! in \3. The replacement just assembles the captures in the right order. Note that you could omit the capture group around the ! and just have an explicit `! in the replacement, but I like to use captures in such contexts as they often allow for shorter replacements (although not in this case) and easier enhancements.
Since the engine is already passed on a comment line to indent it, I think it is impossible to use the same entire edited line for the next match to get the number of spaces. So I think you have to repeat the same replacement more times. Try with:
^(\s*)([^!\s].*?\r\n(\1\!.*?\r\n)*)\s*\!
always replacing it with $1$2$1!.
Like I said in the comment, if you have at most N consecutive comment lines, you will click on the "replace all" button N times
i want to copy the text file and print in on standard output but it skips for every second line
with open("translation.txt") as f:
line = f.readlines()
i=0
while i <len(line):
print line[i]
i=i+1
expected output
one eins
two zwei
three drei
four vier
actual output
one eins
two zwei
three drei
four vier
print adds a new line. Add a trailing comma:
print line[i],
This suppresses the newline.
Your whole program can be reduced to these lines:
with open("translation.txt") as f:
for line in f:
print line,
I recommend to you to use Python 3. If you have to use Python 2 add this as the first line in your program:
from __future__ import print_function
Now you can use the print function in Python 2 and 3:
print(line, end='')
In Python2, the print statement prints an entire line, including a newline character, so the next time it is called the output will be on the next line. You can avoid this by adding a comma at the end of the statement, e.g.:
print line[i],
Further question from my last post: What is this error in fortran and how to stop the program when it occurs?
In my last post, I want to figure out how to identify the reading error when there is not enough elements in the input file which can be solved by using an iostat in the read statement.
My new code is:
program main
implicit none
integer ioerr, switch_1(3), switch_2, i, readerr
open(100, FILE='./input_error.gr', ACTION='READ', IOSTAT=ioerr)
if (ioerr == 0) then
read(100, *, iostat=readerr) (switch_1(i), i=1,3)
if(readerr .ne. 0) then
write(*,*) 'switch 1 wrong'
stop
end if
write(*,*) 'Switch_1 is: ', switch_1
read(100,*,iostat=readerr) switch_2
if(readerr .ne. 0) then
write(*,*) 'switch 2 wrong'
stop
end if
write(*,*) 'Switch_2 is: ', switch_2
else
write(*,*) 'File not read'
end if
end program main
my input file looks like this:
1,2,3
1
My new question is when there is less than three elements in the first line, the program will automatically read elements in the next line for Switch_1 and Switch_2 will have nothing to read and as the program is coded, it will return "Switch 2 wrong".
For example, when the input is like this:
1,3
2
However, what is really wrong is switch_1. Since there is not enough elements for switch_1, it goes to the next line the fill the last position of the array. This is not what I want. What I want is limit the reading in one line so the program will not read another line automatically, and in this case the program can stop at switch_1 and give me 'Switch 1 wrong. Is it possible?
I typically solve this problem by reading the line into a string first, and then attempting to read numbers from the string. For example,
character(len=200) :: str ! Long enough to hold a whole line
integer :: i(3), ier, fid
fid = 100
open(fid, FILE='./input_error.gr', ACTION='READ')
! -- Read a *single* line, and put it all into str
read(fid,'(a)') str
! -- Read str into integer array i
read(str,*,iostat=ier) i(1:3)
! -- Check if the line actually contained 3 integers
if (ier /= 0) then
write(*,*) 'Unsuccessful read'
endif
The read statement is therefore only able to use the current line because that is all str contains.
I figure out that if I add a comment at the end of each line, since character a is different data type, it will not be read as integer numbers. The advantage is when there is not enough elements for each switches, the program will read the comment first instead of reading the next line and give the right error message.
For example, make the input like:
1,2,3 ! Switch 1
4 ! Switch 2
with this structure, even if there is not enough input elements for switch 1, it is not reading 4 as the third element, instead, it is reading the comment, "! Switch 1" which will definitely return an error for Switch 1. This is exactly what I want and this works fine with number reading procedures. However, if the data type of switch_1 is character in the beginning, what will happen? It will not stop at numbers.
I'm trying to print everything in a file with python. But, whenever I use python's built-in readfile() function it only print the first line of my text file. Here's my code:
File = open("test.txt", 'r', 0)
line = File.readline()[:]
print line
and thank you for everyone that answers
and to make my question clearer every time I run the code it prints only "word list food
Is this what you are looking for?
printline = 6
lineCounter = 0
with open('anyTxtFile.txt','r') as f:
for line in f:
lineCounter += 1
if lineCounter == printline:
print(line, end='')
Opens text file, in working directory, and prints printLine
File.readlines()
will, as emre. said, return a list of all the lines in your file. If you'd like to produce a similar result using the readline() command,
s=File.readline()
while s!="":
print s
s=File.readline()
Both methods above leave a newline at the end of each string, except for the last string.
Another alternative would be:
for s in File:
print s
To search for a specific string, or a specific line number, I'd say the first method is best. Looking for a specific line number would be as simple as:
File.readlines()[i]
Where i is the line number you are interested in accessing. Looking for a string is a bit more work, but looping through the list would not be too challenging. Something like:
L=File.readlines()
s="yourStringHere"
i=0
while i<len(L):
if L[i].find(s)!=-1:
break
i+=1
print i
would give you the line number that contained the string you were looking for.
Make it more pythonic.
print_line = 6
with open('input_txt_file.txt', 'r') as f:
for i, line in enumerate(f):
if i == print_line:
print(line, end='')
break
I've got a function in Perl that reads the last modified .csv in a folder, and parses it's values into variables.
I'm finding some problems with the regular expressions.
My .csv look like:
Title is: "NAME_NAME_NAME"
"Period end","Duration","Sample","Corner","Line","PDP OUT TOTAL","PDP OUT OK","PDP OUT NOK","PDP OUT OK Rate"
"04/12/2014 11:00:00","3600","1","GPRS_OUT","ARG - NAME 1","536","536","0","100%"
"04/12/2014 11:00:00","3600","1","GPRS_OUT","USA - NAME 2","1850","1438","412","77.72%"
"04/12/2014 11:00:00","3600","1","GPRS_OUT","AUS - NAME 3","8","6","2","75%"
.(ignore this dot, you will understand later)
So far, I've had some help to parse the values into some variables, by:
open my $file, "<", $newest_file
or die qq(Cannot open file "$newest_file" for reading.);
while ( my $line = <$file> ) {
my ($date_time, $duration, $sample, $corner, $country_name, $pdp_in_total, $pdp_in_ok, $pdp_in_not_ok, $pdp_in_ok_rate)
= parse_line ',', 0, $line;
my ($date, $time) = split /\s+/, $date_time;
my ($country, $name) = $country_name =~ m/(.+) - (.*)/;
print "$date, $time, $country, $name, $pdp_in_total, $pdp_in_ok_rate";
}
The problems are:
I don't know how to make the first AND second line (that are the column names from the .csv) to be ignored;
The file sometimes come with 2-5 empty lines in the end of the file, as I show in my sample (ignore the dot in the end of it, it doesn't exists in the file).
How can I do this?
When you have a csv file with column headers and want to parse the data into variables, the simplest choice would be to use Text::CSV. This code shows how you get your data into the hash reference $row. (I.e. my %data = %$row)
use strict;
use warnings;
use Text::CSV;
use feature 'say';
my $csv = Text::CSV->new({
binary => 1,
eol => $/,
});
# open the file, I use the DATA internal file handle here
my $title = <DATA>;
# Set the headers using the header line
$csv->column_names( $csv->getline(*DATA) );
while (my $row = $csv->getline_hr(*DATA)) {
# you can now access the variables via their header names, e.g.:
if (defined $row->{Duration}) { # this will skip the blank lines
say $row->{Duration};
}
}
__DATA__
Title is: "NAME_NAME_NAME"
"Period end","Duration","Sample","Corner","Line","PDP IN TOTAL","PDP IN OK","PDP IN NOT OK","PDP IN OK Rate"
"04/12/2014 10:00:00","3600","1","GRPS_INB","CHN - Name 1","1198","1195","3","99.74%"
"04/12/2014 10:00:00","3600","1","GRPS_INB","ARG - Name 2","1198","1069","129","89.23%"
"04/12/2014 10:00:00","3600","1","GRPS_INB","NLD - Name 3","813","798","15","98.15%"
If we print one of the $row variables with Data::Dumper, it shows the structure we are getting back from Text::CSV:
$VAR1 = {
'PDP IN TOTAL' => '1198',
'PDP IN NOT OK' => '3',
'PDP IN OK' => '1195',
'Period end' => '04/12/2014 10:00:00',
'Line' => 'CHN - Name 1',
'Duration' => '3600',
'Sample' => '1',
'PDP IN OK Rate' => '99.74%',
'Corner' => 'GRPS_INB'
};
open ...
my $names_from_first_line = <$file>; # you can use them or just ignore them
while($my line = <$file>) {
unless ($line =~ /\S/) {
# skip empty lines
next;
}
..
}
Also, consider using Text::CSV to handle CSV format
1) I don't know how to make the first line (that are the column names from the .csv) to be ignored;
while ( my $line = <$file> ) {
chomp $line;
next if $. == 1 || $. == 2;
2) The file sometimes come with 2-5 empty lines in the end of the file, as I show in my sample (ignore the dot in the end of it, it doesn't exists in the file).
while ( my $line = <$file> ) {
chomp $line;
next if $. == 1 || $. == 2;
next if $line =~ /^\s*$/;
You know that the valid lines will start with dates. I suggest you simply skip lines that don't start with dates in the format you expect:
while ( my $line = <$file> ) {
warn qq(next if not $line =~ /^"\d{2}-\d{2}-d{4}/;); # Temp debugging line
next if not $line =~ /^"\d{2}-\d{2}-d{4}/;
warn qq($line matched regular expression); # Temp debugging line
...
}
The /^"\d{2}-\d{2}-d{4}",/ is a regular expression pattern. The pattern is between the /.../:
^ - Beginning of the line.
" - Quotation Mark.
\d{2} - Followed by two digits.
- - Followed by a dash.
\d{2] - Followed by two more digits.
- - Followed by a dash.
\d{4} - Followed by four more digits
This should be describing the first part of your line which is the date in MM-DD-YYYY format surrounded by quotes and followed by a comma. The =~ tells Perl that you want the thing on the left to match the regular expression on the right.
Regular expressions can be difficult to understand, and is one of the reasons why Perl has such a reputation of being a write-only language. Regular expressions have been likened to sailor cussing. However, regular expressions is an extremely powerful tool, and worth the effort to learn. And with some experience, you'll be able to easily decode them.
The next if... syntax is similar to:
if (...) {
next;
}
Normally, you shouldn't use post-fix if and never use unless (which is if's opposite). They can make your program more difficult to understand. However, when placed right after the opening line of a loop like this, they make a clear statement that you're filtering out lines you don't want. I could have written this (and many people would argue this is preferable):
next unless $line =~ /^"\d{2}-\d{2}-d{4}",/;
This is saying you want to skip lines unless they match your regular expression. It's all a matter of personal preference and what do you think is easier for the poor schlub who comes along next year and has to figure out what your program is doing.
I actually thought about this and decided that if not ... was saying that I expect almost all lines in the file to match my format, and I want to toss away the few exceptions. To me, next unless ... is saying that there are some lines that match my regular expression, and many lines that don't, and I want to only work on lines that match.
Which gets us to the next part of programming: Watching for things that will break your program. My previous answer didn't do a lot of error checking, but it should. What happens if a line doesn't match your format? What if the split didn't work? What if the fields are not what I expect? You should really check each statement to make sure it actually worked. Almost all functions in Perl will return a zero, a null string, or an undef if they don't work. For example, the open statement.
open my $file, "<", $newest_file
or die qq(Cannot open file "$newest_file" for reading.);
If open doesn't work, it returns a file handle value of zero. The or states that if open doesn't return a non-zero file handle, execute the line that follows which kills your program.
So, look through your program, and see any place where you make an assumption that something works as expected and think what happens if it didn't. Then, add checks in your program to something if you get that exception. It could be that you want to report the error or log the error and skip to the next line. It could be that you want your program to come to a screeching halt. It could be that you can recover from the error and continue. What ever you do, check for possible errors (especially from user input) and handle possible errors.
Debugging
I told you regular expressions are tricky. Yes, I made a mistake assuming that your date was a separate field. Instead, it's followed by a space then the time which means that the final ", in the regular expression should not be there. I've fixed the above code. However, you may still need to test and tweak. Which brings us into debugging in Perl.
You can use warn statements to help debug your program. If you copy a statement, then surround it with warn qq(...);, Perl will print out the line (filling out variables) and the line number. I even create macros in my various editors to do this for me.
The qq(...) is a quote like operator. It's another way to do double quotes around a string. The nice thing is that the string can contain actual quotation marks, and the qq(...); will still work.
Once you've finished debugging, you can search for your warn statements and delete them. Perl comes with a powerful built in debugger, and many IDEs integrate with it. However, sometimes it's just easier to toss in a few warn statements to see what's going on in your code -- especially if you're having issues with regular expressions acting up.