텍스트 파일을 조작하고 싶습니다. 다음과 같은 형태의 블록이 많이 포함되어 있습니다.
CLASS
...some stuff ...
END
각 블록을 복사하고 해당 내용의 한 줄을 추가 및 제거하고 싶습니다. 스크립트를 작성할 수 있나요?
답변1
알았어 너할 수 있는무엇이든 쓰세요.
그러나 이렇게 하면 vim
매크로를 사용하게 됩니다. (아직 익숙하지 않다면 vim
배워야 하고, 그렇지 않다면 무시하세요)
몇 가지 기본 지침:
q - 매크로 기록 시작
qx -- 매크로 기록을 중지하고 이름을 "x"로 지정합니다.
@x -- "x"라는 매크로를 실행합니다.
매크로는 기록 세션 중에 입력한 모든 명령을 즉시 다시 실행합니다.
따라서 매크로가 다음과 같이 블록을 복사하도록 하려면:
q start macro
/CLASS jump to next "CLASS"
V start selecting full lines
/END jump to next "END
Y yank selected lines (yank = copy)
j scroll down one line
p put (paste)
qd stop recording and name the macro d
vim 사용법과 vim 매크로에 대한 좋은 리소스와 예제가 많이 있습니다.
가치 있는 점은 sed가 vim의 명령줄 버전이기 때문에 내가 말하는 내용을 sed에 적용할 수 있을 수도 있지만, 저는 그것에 익숙하지 않기 때문에 보장할 수 없습니다.
~~편집~~
더 유용하게 만드는 또 다른 점은 vim
여러 파일을 열 수 있다는 것입니다. 여러 개의 열린 파일을 버퍼라고 합니다. 여러 파일 이름을 추가하여 이 기능을 활성화할 수 있습니다 vim
(IE는 vim *.txt
모든 txt 파일을 엽니다).
여러 버퍼에서 매크로를 실행하려면 먼저 모든 파일을 동시에 엽니다. 그런 다음 각 버퍼에서 :bufdo normal @x
매크로 실행을 사용하십시오.x
:w
현재 버퍼가 저장되지 않은 경우 다음 버퍼로 전환하려고 시도하는 동안 중단되는 것을 방지하려면 이 단계를 매크로의 마지막 단계로 만들어야 합니다 .
:bn
수동으로 다음 버퍼로 이동합니다.
또한보십시오https://stackoverflow.com/questions/1291962/replay-a-vim-macro-until-end-of-buffer각 행에 대해 매크로를 실행하는 방법을 알아보세요. 리안리안칸 :)
답변2
이 목적을 위한 자연스러운 도구는 awk와 Perl입니다(스크립트를 작성한다고 가정하면 일회성이며 자연 도구는 대화형 편집기입니다). 다음은 모든 CLASS
... 블록을 복사하는 awk 스크립트입니다 END
(균형 조정 지원 안 함: 각 블록이 CLASS
다음 블록과 일치함 END
). 그러나 foo
두 번째 복사본에서는 줄이 생략됩니다.
awk '
/^CLASS$/ { store = 1; } # start storing
store && ! /^foo$/ { hold = hold ORS $0; } # if storing, maybe save line
/^END$/ {
$0 = $0 hold; # append hold copy to current line
store = 0; hold = ""; # end of block
}
1 { print; } # print original line, with hold prepended if at end of block
'
이것은 sed 솔루션입니다. 너무 심각하게 받아들이지 마십시오. CLASS
/ 줄이 엄격하게 번갈아 표시되지 않으면 작동할 것이라고 기대하지 마세요 END
.
sed -e '/^CLASS$/,/^END$/!b' \
-e '/^CLASS$/{' -e 'h' -e 'b' -e '}' \
-e '/^foo$/!H' \
-e '/^END$/G'
답변3
사용되는 정확한 도구는 작업의 세부 사항에 따라 다릅니다. 작업이 한 번만 발생하는 경우 vim
또는 에서 매크로 사용을 고려할 수 있습니다 emacs
. 정말로 스크립트를 작성하고 싶다면 다음을 살펴보겠습니다 sed
.
Sed는 스트림 편집기입니다. 스트림 편집기는 입력 스트림(파일 또는 파이프의 입력)에서 기본 텍스트 변환을 수행하는 데 사용됩니다.
이 작업을 수행하는 정확한 방법은 상황에 따라 다르지만 PATTERN으로 시작하는 줄 뒤에 줄을 추가하려면 다음을 수행할 수 있습니다.
sed -e 's/\(^PATTERN.*\)/\1\nTextToAdd/' file.old > file.new
PATTERN으로 시작하는 줄 앞에 줄을 추가하려면 다음을 수행하세요.
sed -e 's/\(^PATTERN.*\)/TextToAdd\n\1/' file.old > file.new
PATTERN으로 시작하는 줄 삭제
sed -e 's/\(^PATTERN.*\)//' file.old > file.new
비결은 원하는 선만 캡처할 수 있는 올바른 패턴을 찾는 것입니다.
다음을 수행하여 이를 결합할 수 있습니다.
sed -e 's/\(^PATTERN1.*\)/\1\nTextToAdd/' -e 's/\(^PATTERN2.*\)/TextToAdd\n\1/' file.old > file.new
답변4
내 Python 솔루션:
file = open('a.txt', 'r')
arr = []
tmp = []
remember = False
for line in file:
if "CLASS" in line:
remember = True # start storing lines
tmp.append(line) # we're storing lines in list
continue # go to next line
if "END" in line:
tmp.append(line) # store line
remember = False # stop storing lines
arr.append(tmp) # add line to list
tmp = [] # clear temp list
continue # go to next line
if remember:
tmp.append(line) # add to list line between CLASS and END
file.close()
file = open('a.txt', 'a')
for tmp in arr:
if ' ...some stuff ...1\n' in tmp: # we can skip
continue # whole block if we find this
for i in tmp:
if "333" in i: # we can skip only one line
continue
file.write(i)
file.close()
awk 버전보다 이해하고 수정하기가 가장 쉬운 것 같아요(awk를 모르는 경우)... 그런데, awk는 제가 배우고 싶은 언어 목록의 다음 언어입니다... ;)