1

I'm having some difficulty with writing a program in Python. I would like the program to read lines between a set of characters, reverse the order of the lines and then write them into a new file. The input is:

AN10 G17 G21 G90
N20 '2014_12_08_Banding_Test_4
N30 M3 S1B
N40G00X0.000Y0.000Z17.000
N50 G00X0.001Y0.001Z17.000
N60 G01Z0.000F3900.0
N70 G01X0.251
N80 G01X149.999
N90 G01Y0.251
N100 G01X149.749
N110 G01X149.499Z-8.169
N120 G01X148.249Z-8.173
N130 G01X146.999Z-8.183
N140 G01X145.499Z-8.201
...
N3140 G01Y0.501

So far my code is:

with open('Source.nc') as infile, open('Output.nc', 'w') as outfile:
    copy = False
    strings_A = ("G01Y", ".251")
    strings_B = ("G01Y", ".501")
    content = infile.readlines()
    for lines in content:
        lines.splitlines(1)
        if all(x in lines for x in strings_A):
            copy = True
        elif all(x in lines for x in strings_B):
            copy = False
        elif copy:
            outfile.writelines(reversed(lines))

I think I am failing to understand something about the difference between lines and a multi-multiline string. I would really appreciate some help here!

Thanks in advance, Arthur

Droppy
  • 9,691
  • 1
  • 20
  • 27
  • splitlines is a methode that returns something, but you ignore the return value. So this statement has no influence and can be removed from the program – miracle173 Dec 12 '14 at 12:49
  • I don't understand your description of the algorithm. What do you mean by "read lines between a set of characters". Is the order of the lines reversed or the order of the characters of each line. It woul help if you add the expectedd output to your input. You should try to debug your program and check if the variables have the contetn you expect. – miracle173 Dec 12 '14 at 12:55

1 Answers1

2

A string has multiple lines if it contains newline characters \n.

You can think of a file as either one long string that contains newline characters:

s = infile.read()

Or you can treat it like a list of lines:

lines = infile.readlines()

If you have a multiline string you can split it into a list of lines:

lines = s.splitlines(False)
# which is basically a special form of:
lines = s.split('\n')

If you want to process a file line by line all of the following methods are equivalent (in effect if not in efficiency) :

with open(filename, 'r') as f:
  s = f.read()
  lines = s.splitlines()
  for line in lines:
    # do something
    pass

with open(filename, 'r') as f:
  lines = f.readlines()
  for line in lines:
    # do something
    pass

# this last option is the most pythonic one, 
#   it uses the fact that any file object can be treated as a list of lines
with open(filename, 'r') as f
  for line in f:
    # do something
    pass

EDIT Now the solution of your problem:

with open('Source.nc') as infile, open('Output.nc', 'w') as outfile:
    copy = False
    strings_A = ("G01Y", ".251")
    strings_B = ("G01Y", ".501")
    target_lines = []
    for line in infile:
        if copy and all(x in line for x in strings_B):
            outfile.writelines(reversed(target_lines))
            break

        if copy:
          target_lines.append(line)

        if all(x in line for x in strings_A):
            copy = True

This will copy all lines between a line that matches all(x in line for x in strings_A) and a line that matches all(x in line for x in strings_B) into the outfile in reversed order. The identifying lines are NOT included in the output (I hope that was the intent). The order of the if clauses is deliberate to achieve that.

Also be aware that the identification tests (all(x in line for x in strings_A)) you use, work as a substring search not a word match, again I don't know if that was your intent.

EDIT2 In response to comment:

with open('Source.nc') as infile, open('Output.nc', 'w') as outfile:
    strings_A = ("G01Y", ".251")
    strings_B = ("G01Y", ".501")
    do_reverse = False
    lines_to_reverse = []
    for line in infile:
        if all(x in line for x in strings_B):
           do_reverse = False
           outfile.writelines(reversed(lines_to_reverse))
           outfile.writeline(line)
           continue

        if do_reverse:
          lines_to_reverse.append(line)
          continue
        else:
          outfile.writeline(line)

        if all(x in line for x in strings_A):
          do_reverse = True
          lines_to_reverse = []
PeterE
  • 5,715
  • 5
  • 29
  • 51
  • Peter. Thank you very much. This is a significant step towards what I am trying to achieve. I would like the text within the "target_lines" to be reversed and the other lines outside of this string to retain their original order so it looks like this: AN10 G17 G21 G90 N20 '2014_12_08_Banding_Test_4 N30 M3 S1B N40G00X0.000Y0.000Z17.000 N50 G00X0.001Y0.001Z17.000 N60 G01Z0.000F3900.0 N70 G01X0.251 N80 G01X149.999 N90 G01Y0.251 #now this bit is reversed N100 G01X149.749 N110 G01X149.499Z-8.169 N120 G01X148.249Z-8.173 N130 G01X146.999Z-8.183 N140 G01X145.499Z-8.201 #until here N3140 G01Y0.501 – Arthur Prior Dec 12 '14 at 13:06
  • Peter send me an email arthur.prior@me.com - I have a proposition for you ;) – Arthur Prior Dec 12 '14 at 14:23