python - 원하는 문자열 추출이 어렵는데요.

sptxnspt의 이미지

생산현장에 쓰는 CNC 컨트롤러에는 실제로 아래처럼 프로그램 data가 txt화일로 들어 있습니다.
이를 영문자 'O'와 숫자 4자리로 시작하는 '프로그램 번호'별로 문자열을 추출하고 싶은데,,,M99로 끝나는
경우는 안되는 군요. 파이썬 입문자 입니다. 도움 부탁해요;

<원하는 결과> O0001(MACRO Z- STEPOVER) #101=0. M30 ------ O0002(WARMING-UP) #110=1. IF[#110GT#111]GOTO25 M99 ------- O0003(HELICAL X TEST OK W/MACRO W/G41) #101=1.5(STEPOVER/REV) M30 -------- O0008(SUB OF O0007) G10L20P1G90X-#24Y-#25Z0. M99 --------- O0007(#10~#60 BLOCK-COOLANT) /G65P0008X653.46Y295.73 M30 ------- O0015(HIGH SPEED TEST-E/M D10. ZE504) (GOOD,V=267 AE=0.05D AP=0.9D,AL6061) M30 -------- O8523(DNM400 CIRCULAR INTERPOLATION RADIUS SUB-PRO.) G91G28G0Z0 M99 -------- . . .

#cncdata.py

```{.python}
data = '''
%
O0001(MACRO Z- STEPOVER)
#101=0.
M30
O0002(WARMING-UP)
#110=1.
IF[#110GT#111]GOTO25
M99
O0003(HELICAL X TEST OK W/MACRO W/G41)
#101=1.5(STEPOVER/REV)
M30
O0008(SUB OF O0007)
G10L20P1G90X-#24Y-#25Z0.
M99
O0007(#10~#60 BLOCK-COOLANT)
/G65P0008X653.46Y295.73
M30
O0015(HIGH SPEED TEST-E/M D10. ZE504)
(GOOD,V=267 AE=0.05D AP=0.9D,AL6061)
M30
O8523(DNM400 CIRCULAR INTERPOLATION RADIUS SUB-PRO.)
G91G28G0Z0
M99
% '''

count = 0

for line in data.split('M30'):
print('-'*10)
print(line+'M30')
count += 1

print(count)

익명_사용자의 이미지

차라리 awk를 써보시는건 어떨까요?

$ cat input.txt 
O0001(MACRO Z- STEPOVER)
#101=0.
M30
O0002(WARMING-UP)
#110=1.
IF[#110GT#111]GOTO25
M99
O0003(HELICAL X TEST OK W/MACRO W/G41)
#101=1.5(STEPOVER/REV)
M30
O0008(SUB OF O0007)
G10L20P1G90X-#24Y-#25Z0.
M99
O0007(#10~#60 BLOCK-COOLANT)
/G65P0008X653.46Y295.73
M30
O0015(HIGH SPEED TEST-E/M D10. ZE504)
(GOOD,V=267 AE=0.05D AP=0.9D,AL6061)
M30
O8523(DNM400 CIRCULAR INTERPOLATION RADIUS SUB-PRO.)
G91G28G0Z0
M99
$
$
$ awk '$1 ~ /^O[0-9]{4,4}([^0-9]{1,1}|$)/,$1 ~ /^M[0-9]{1,}/ { print $0; if ($1 ~ /^M[0-9]{1,}/) {print("---------");}}' input.txt
O0001(MACRO Z- STEPOVER)
#101=0.
M30
---------
O0002(WARMING-UP)
#110=1.
IF[#110GT#111]GOTO25
M99
---------
O0003(HELICAL X TEST OK W/MACRO W/G41)
#101=1.5(STEPOVER/REV)
M30
---------
O0008(SUB OF O0007)
G10L20P1G90X-#24Y-#25Z0.
M99
---------
O0007(#10~#60 BLOCK-COOLANT)
/G65P0008X653.46Y295.73
M30
---------
O0015(HIGH SPEED TEST-E/M D10. ZE504)
(GOOD,V=267 AE=0.05D AP=0.9D,AL6061)
M30
---------
O8523(DNM400 CIRCULAR INTERPOLATION RADIUS SUB-PRO.)
G91G28G0Z0
M99
---------

다음의 awk 한문장이면 됩니다.

awk '$1 ~ /^O[0-9]{4,4}([^0-9]{1,1}|$)/,$1 ~ /^M[0-9]{1,}/ { print $0; if ($1 ~ /^M[0-9]{1,}/) {print("---------");}}' input.txt

필요하시면 regex 더 엄격하게 만드시면 됩니다.

익명 사용자의 이미지

패턴이 있는 경우는 파이썬 보다 awk 가 정답같네요.
덕분에 해결되었습니다.

sptxnspt의 이미지

인터넷으로 awk 문법을 보고 간단한 사용법이고 이해되어서 해결되었다고 생각했는데
막상 윈도우에서 awk 설치나 명령어 사용이 안되는 군요.,,급당황.
Gnu32win 을 설치하고나서 cmd 화면에서 사용이 가능하네요.
암튼 감사하고요,
한편으론 파이썬으로 가능한 로직도 알고 싶어집니다.^^ cmd 창이 부담스러워서요.

익명_사용자의 이미지

awk가 하는것을 python으로 똑같이 구현하셔야합니다.
걸러내야하는 입력데이터의 패턴이 얼마나 많으냐에따라 좀 지저분해질수도 있는데, 대략 다음과 같습니다.

#cncdaata.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
class Status:
    BEGIN = 0
    END = 1
 
with open("input.txt", "r") as handle:
    nextStatus = Status.BEGIN
    for line in handle:
        # 만약 다음와야 하는 상태가 BEGIN이면, O로 시작하고, 4개의 숫자로 구성된
        # 프로그램별 번호가 와야한다.
        # 아니라면, 뭔가 이상한 입력이니 무시.
        if nextStatus == Status.BEGIN:
            if re.match(r"^O\d{1,4}(\D{1,4}|$)", line):
                print line,
                nextStatus = Status.END
 
        # 다가오는 라인의 시작이 M\d{1,}이면 현재 프로그램 입력의 마지막을 의미.
        elif nextStatus == Status.END:
            print line,
            if re.match(r"^M\d{1,4}", line):
                print "---------------------------"
                nextStatus = Status.BEGIN

sptxnspt의 이미지

잘되니까 고마운데요,,,,고민이 생기네요.
재밋고 쉬워보여서 파이썬을 배우기 시작했는데(인터넷 정보가 많더군요)
-하는 일에 직접 활용하려고요,
하는 일은 복잡한 일도 아니어서 지금까지는 액셀과 액세스기본기 정도로 오가며
시간 좀 들여서 그냥그냥 해왔어요,
파이썬을 보고는..활용하면 어느정도 노가다를 피할 수 있겠다는 생각으로 덤볐는데

막 배우는 입장에서 위 코드를 보니까 파이썬이 겁나고 벽처럼 느껴집니다.
클래스/인스턴스를 어느 정도 이해했다고 생각했는데
아래 문장은 쓰는 의도가 전혀 이해 안되고,,
뭘 봐야 이런 문장을 이해 할수 있을 지..멍해지네요

'''
class Status:
BEGIN = 0
END = 1

nextStatus = Status.BEGIN
'''

암튼 감사함다.

익명_사용자의 이미지

그건 코드의 가독성을 위해서입니다. 코드의 가독성에 대해 근본적으로 이해하시려면,
과연 좋은 코드는 무엇인가 부터 시작해서, 어떻게 코드를 유지보수 관리해야하는가에 대한 방법론까지, 그리고
넓게보면 디자인 패턴까지 공부하셔야합니다.
이건 단지 책을 많이 읽는것만으로는 부족하고
많이 경험해보고 코드를 많이 짜봐야합니다.

질문하신부분은 class를 단지 네임스페이스로 사용하여 몇개의 미리 정의된 값들을 사람이 파악하기 쉬운 이름으로 정의해주는 부분입니다.
아래의 코드처럼 1이나 2같이 사람이 의미를 파악하기 힘든 값들을 직접 사용했다면, status의 종류가 많아지고
코드의 길이가 길어졌을때 관리하기가 힘듭니다.

if nextStatus == 1:
    print ....
elif nextStatus == 2:
    print ...

익명 사용자의 이미지

네임스페이스 설명에서 갑자기 코드가 이해 됩니다.
쉬운구별겸, 방향타 역할,,

BEGIN에서 시작해서 nextStatus 에 의해 elif의 END로 가서 line 을 계속 print 하다가 M--울 만나면 다시
BEGIN의 if 로 가서 O----를 체크하고...

잘은 모르지만 잔짜 이런 방법 써먹을 일이 많겠다는 생각이 듭니다.
다시 파이썬에 의욕이 생기네요.
고맙슴다.^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.