나는 프로그래밍 경험이 거의 없으며 현재 기술을 향상시키기 위해 노력하고 있습니다. 기본적으로 .txt 파일의 일부 데이터에 대해 특정 처리를 수행할 수 있는 프로그램을 작성해야 합니다.
처음부터 다음과 같은 데이터가 포함된 .txt 파일이 있습니다.
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrstuv
>tex_4 abcdefghijklmnopqrst
// x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrst
>tex_4 abcdefghijklmnopqrstuv
// x x
>tex_1 abcdefghijklmnopqrstuv
>tex_2 abcdefghijklmnopqrstuv
// x x
내가 사용하고 있는 소프트웨어에서 분석할 수 있는 데이터 세트를 얻으려면 이 데이터로 몇 가지 이상한 작업을 수행해야 합니다. 각 "//..." 줄은 다음 "//..." 줄까지 위의 데이터 그룹을 나타냅니다.
내가 하고 싶은 일의 목록은 다음과 같습니다.
참조하는 데이터 그룹이 위가 아닌 아래에 있도록 "//..." 줄을 이동합니다.
// x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrstuv
>tex_4 abcdefghijklmnopqrst
// x x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrst
>tex_4 abcdefghijklmnopqrstuv
// x x
>tex_1 abcdefghijklmnopqrstuv
>tex_2 abcdefghijklmnopqrstuv
줄의 나머지 텍스트를 이동하지 않고 // 뒤에 각 그룹에 고유한 이름을 추가합니다.
//Name 1 x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrstuv
>tex_4 abcdefghijklmnopqrst
//Name 2 x x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrst
>tex_4 abcdefghijklmnopqrstuv
//Name 3 x x
>tex_1 abcdefghijklmnopqrstuv
>tex_2 abcdefghijklmnopqrstuv
원본 파일을 변경하지 않고 새 파일로 출력합니다. 그런 다음 아래의 각 이름 행 + 행을 잡고 File2에 출력합니다.
//Name 1 x
>tex_1 abcdefghijklmnopqrstu
//Name 2 x x
>tex_1 abcdefghijklmnopqrstu
//Name 3 x x
>tex_1 abcdefghijklmnopqrstuv
구조를 변경하고 다음과 같이 이름을 지정한 후 File3에 출력합니다.
>Name 1 abcdefghijklmnopqrstu
>Name 2 abcdefghijklmnopqrstu
>Name 3 abcdefghijklmnopqrstuv
위의 데이터는 구조이므로 실제로 분석할 수 있습니다.
이제 나는 이것이 어려운 작업이라는 것을 알고 있습니다. "어떻게 프로그래밍합니까?"라고 묻는 것이 아닙니다. 이런 프로젝트를 어디에서 시작하시겠습니까? 이 프로젝트에 어떤 언어가 가장 적합하다고 생각하시나요?
저는 이 사이트에서 도움을 받아 UNIX에서 몇 가지 작업을 수행할 수 있었습니다. 예를 들어, 다음 Unix 코드를 사용하여 각 "//..." 줄에 고유한 이름을 지정합니다.
awk -F '' '/\/\//{n++ ; t=" Name "n ; sub("// {0,"length(t)-1"}","//"t)}{print}' File1.txt
어디서부터 시작해야 할지 몇 가지 팁을 주실 수 있나요?
이 질문이 Python 프로젝트에 적합한가요?
원시 .txt 데이터 파일에는 많은 양의 데이터가 포함되어 있으므로 수동으로 처리할 수 없습니다. 또한 이 프로젝트는 프로그래밍을 더 깊이 탐구하는 방법입니다.
답변1
나에게 이것은 파이썬 작업처럼 보입니다. 일반적인 경험 법칙: 작업에 "플랫" 및 콘텐츠 블라인드 처리만 필요한 경우 핵심 유틸리티(바람직하게는 gnu)가 최선의 선택입니다. 이는 문자열 대체, 삭제, 줄 기반 처리, 간단한 정렬, 계산, 필터링 등에 작동합니다. 이러한 도구를 사용하면 원하는 작업을 매우 빠르게 수행하는 코드 줄을 작성할 수 있으며 연습을 통해 이러한 작업을 수행할 수 없습니다. 심지어 많은 생각이 필요합니다.
반면에 계층적(트리와 같은) 구조, 사용자 정의 구분 기호 및 컨텍스트 인식 문자열을 암시하는 파일 보기가 필요한 복잡한 작업이 있는 경우 파일 언어에서 동일한 구조를 사용하여 프로그래밍하는 것이 더 쉬울 것입니다. 극단적인 예는 html/xml/json 파일, 중괄호가 중첩된 모든 파일 등입니다. 사용 가능한 매우 강력한 데이터 구조가 있는 경우(Python에서는 가능), 읽은 후 Object is handler andexit와 같은 곳에 작성하면 됩니다. . 여전히 awk에서(또는 sed에서 조금 더 노력하면) 할 수 있지만 그만한 가치는 없습니다.
귀하의 경우에는 이전 마크의 위치를 기억해야 합니다(또는 긴 버퍼를 유지해야 합니다). 이는 라인 처리 소프트웨어에 약간 다루기 어렵습니다. 하지만 파이썬에서는 이것이 쉽습니다.
샘플 코드:
#!/usr/bin/python
import sys
with open(sys.argv[1],'r') as file, open(sys.argv[2],'w') as file1, open(sys.argv[3],'w') as file2, open(sys.argv[4],'w') as file3:
counter = 1
current_buffer = []
for line in file:
if line.startswith('//'):
#we found a delimiter, flush the buffer
#could use regular expressions, but for the sake of this example
#this is enough
prefix = '//Name {}'.format(counter)
new_header = prefix+line[len(prefix):]
file1.write(new_header)
file2.write(new_header)
for oldline in current_buffer:
file1.write(oldline)
if current_buffer: #only first line to file 2
first_line = current_buffer[0]
file2.write(first_line)
#same here, could use regular expressions from "import re" but we don't have to
rest_of_line = first_line.split(' ',1)[1]
file3.write('//Name {} {}\n'.format(counter,rest_of_line.strip()))
current_buffer=[]
counter+=1
else:
current_buffer.append(line)
#if the file is well-formatted, current_buffer should be empty now - otherwise, do special handling
전화해서 ./test.py inputfile file1 file2 file3
그것이 당신이 원하는 것인지 확인하세요.
답변2
가장 편안한 방법을 선택해야 합니다. 즉, 새로운 도구 사용법을 배우는 것도 피해서는 안 됩니다. 저는 이 도구에 매우 만족 sed
하며 특히 이 작업에 적합하다고 생각하여 nl
두 도구를 조합하여 사용합니다.
<<\INFILE \
nl -bp'^//' -w1 -s' ' |\
sed -ne ' s|^ *>|>|;//H;x;//x;t' -e 'G
x;s|.*|### The following is written to: File1|p
x;s|\([0-9]*\)\( *\)\( \)*//\2|//Name \1\3|pw File1
x;s|1|2|p;x;s|\n\(\n.*\)*|&&|2;s|||2p;w File2' -e 'x;s|2|3|p
x;s|//\([^ ]* [^ ]*\).*\n[^ ]*|>\1|pw File3'
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrstuv
>tex_4 abcdefghijklmnopqrst
// x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrst
>tex_4 abcdefghijklmnopqrstuv
// x x
>tex_1 abcdefghijklmnopqrstuv
>tex_2 abcdefghijklmnopqrstuv
// x x
...이것이 트릭을 수행하는 것 같습니다.
내가 말할 때nl
이 작업에 매우 적합--separator
패턴에 따라 블록을 순차적으로 쉽게 번호를 매기고 , 번호가 매겨진 줄의 텍스트와 줄 번호 사이에 임의의 문자열을 삽입하는 것 외에도 nl
줄은 항상 들여쓰기되기 때문입니다.번호 없음추가하는 들여쓰기와 일치하도록 합니다.
^//
이는 패턴과 일치 하도록 번호가 매겨지지 않은 모든 줄이 이제 <space>
. 따라서 실제 텍스트가 예제의 데이터보다 훨씬 더 복잡하더라도 sed
실제로는 매우 쉽습니다. 실제로 위 작업의 대부분은 의미 있는 디버그 출력을 생성하는 것입니다 sed
. 완전한 기능을 갖춘 명령문은 다음과 같이 간단할 수 있습니다.
nl -bp'^//' -w1 -s' ' <infile |
sed -ne 's|^ *>|>|;//H;x;//x;t' -e 'G;h
s|\([0-9]*\)\( *\)\( \)*//\2|//Name \1\3|w File1
s|\n|&&|2;s|\n\n.*||;w File2
s|//\([^ ]* [^ ]*\).*\n[^ ]*|>\1|w File3'
나는 당신의 말에 조금 혼란스러워요줄의 나머지 텍스트를 이동하지 마십시오왜냐하면 그것은 당신의 예와 모순되는 것 같기 때문입니다.(그리고 가능성의 영역). 내가 이렇게 말하는 이유는 다음과 같습니다.
// x
...분명히 양도됐어조금오른쪽으로 변환되면 다음과 같습니다.
//Name 1 x
...사실은1그리고엑스두 예제 모두에서 동일한 열을 차지합니다. 중간에 이 모순을 해결하려고 노력 중입니다. 문자가 아닌 항목을 덮어쓰지 않는 한 텍스트를 이동하지 않고 쌍과 공백을 <space>
계속 삽입합니다 .Name [num]
따라서... 사이의 차이는 고려되지 않습니다.
//Name 3 x x
...그리고...
// x x
...무시했습니다(희망?)예제의 버그입니다.
내 파이프는 모든 것을 표준 출력으로 인쇄하지만, 다음으로 시작하는 줄 뒤의 블록 ###
도 지정된 파일에 차례로 추가됩니다. 내 파이프라인이 인쇄하는 내용은 다음과 같습니다.
### The following is written to: File1
//Name 1 x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrstuv
>tex_4 abcdefghijklmnopqrst
### The following is written to: File2
//Name 1 x
>tex_1 abcdefghijklmnopqrstu
### The following is written to: File3
>Name 1 abcdefghijklmnopqrstu
### The following is written to: File1
//Name 2 x x
>tex_1 abcdefghijklmnopqrstu
>tex_2 abcdefghijklmnopqrstuv
>tex_3 abcdefghijklmnopqrst
>tex_4 abcdefghijklmnopqrstuv
### The following is written to: File2
//Name 2 x x
>tex_1 abcdefghijklmnopqrstu
### The following is written to: File3
>Name 2 abcdefghijklmnopqrstu
### The following is written to: File1
//Name 3 x x
>tex_1 abcdefghijklmnopqrstuv
>tex_2 abcdefghijklmnopqrstuv
### The following is written to: File2
//Name 3 x x
>tex_1 abcdefghijklmnopqrstuv
### The following is written to: File3
>Name 3 abcdefghijklmnopqrstuv
답변3
이 경우 Python이 더 적합하다는 데 동의하지 않습니다. 어려운 줄 조작이 없습니다. 변수를 설정하고 다양한 변수 세트를 인쇄하기만 하면 됩니다. 이것이 일반적인 bash 작업입니다. 따라서 awk
대신 내가 선호하는 몇 가지 계산이 필요합니다 sed
(일반적인 텍스트 조작 프로그램).
awk -F '' '
/\/\//{
n++
t="Name "n" "
sub("// {0,"length(t)"}","//"t)
print $0 "\n" l1 l2 > "File2"
print $0 "\n" l1 > "File3"
sub("[^ ]* ","<"t,l1)
print l1 > "data.file"
l1=""
l2=""
next
}
{
if (l1=="")
l1=$0
else l2=l2 "\n" $0
}' Input.txt
그러나 모든 사람은 자신이 더 잘 아는 도구를 선호합니다.
PS 입력 문자열의 길이에 관해서. OP가 귀하의 예를 확인하면 볼 수 있습니다«x» is above «e»
// x
>tex_1 abcdefghijklmnopqrstu
하지만 들어가고 나면Name 1
«x» is above «d»
//Name 1 x
>tex_1 abcdefghijklmnopqrstu
length(t)
따라서 스크립트에서는 lenght(t)-1
. 또한 이름 스크립트를 입력할 공간이 충분하지 않은 경우 문자열의 나머지 부분을 오른쪽으로 이동해야 합니다.