sed

sed

파일에서 무작위로 발견되므로 위치를 기억할 필요 없이 두 패턴 사이의 텍스트를 인쇄해야 합니다. 텍스트가 같은 줄에 나타나거나 같은 줄에 나타나지 않거나 그 사이에 나타납니다.

패턴은 다음 <abc>과 같습니다.</abc>

예:

aslkdjas<abc>aaaa</abc><abc>bbbb</abc>sdkljasdl<abc>
cccc
dddd</abc>ieurwioeru<abc>eeee</abc>asdasd

두 패턴 사이의 값을 표시하려면 다음과 같은 출력이 필요하거나 이 파일에서 발생하는 모든 작업을 쉼표로 구분해야 합니다.

aaaa
bbbb
cccc
dddd
eeee

답변1

기능 코드를 구문 분석하기 위해 텍스트 처리 도구를 사용하지 않는 것이 좋습니다. 그것들은 인간의 언어를 구문 분석하도록 설계되었으며 조만간 해결할 수 없는 문제에 직면하게 될 것입니다. 특수 도구(html 인터프리터, C++ 컴파일러 등)를 사용하세요.

이 경우 다음을 시도해 볼 수 있습니다 pcregrep.

pcregrep -Mo '<abc>\K(.|\n)*?(?=</abc>)' file

밝혀지다

aaaa
bbbb

cccc
dddd
eeee

bbbbcccc예, 원본 파일에 새 줄이 있었기 때문에 와 사이에 새 줄이 있습니다 . 물론 원하는 경우 공백을 제거하기 위해 출력을 파이프할 수 있습니다(사용 tr또는 기타 방법) sed. 그러나 앞서 말했듯이 실제 사례에서는 예상치 못한 결과가 더 많이 발생할 수 있습니다.

답변2

이 간단한 경우에는 다음을 시도하십시오.

sed ':L1; N; $bL2; bL1; :L2; s#<abc>#^A#g; s#^[^^A]*^A##; s#</abc>[^^A]*^A#\n#g; s#</abc>.*$##; ' file
aaaa
bbbb

cccc
dddd
eeee

모든 라인을 패턴 공간으로 수집하고, 선행 패턴을 로 바꾸고 ^A, BOL을 첫 번째로 제거하고 ^A, 패턴 사이의 문자열을 로 바꾸고 <new line>, EOL까지 패턴을 제거하고, 인쇄합니다.

답변3

sed

sed 솔루션은 패턴을 파일의 다른 곳에서는 사용되지 않는 다른 두 문자로 변환하는 것입니다. 이는 문제를 두 개의 단일 문자 사이의 추출에 대한 일반적인 문제로 바꿉니다.

  1. 먼저 각 패턴을 단일 문자로 변환합니다.

    sed 'H;$!d;x; s##^A#g;'

    Ctrl각각에 대해 - -를 입력했다고 가정하면 V Ctrl에도 비슷한 명령이 입력되었습니다.A^A^B

    처음에는 H;$!d;x;패턴 공간의 전체 파일이 캡처됩니다. 이는 다음을 의미합니다.

    • 모든 라인을 지켜라
    • 패턴 공간을 지우고 처음으로 돌아갑니다.d
    • 만약에이것은아니요마지막 줄$!
    • 예약된 공간에 저장된 모든 행을 가져옵니다 x. (아마도 gx는 예약된 공간에서 패턴 공간으로 전체 파일이 복사되지 않으므로 더 적은 메모리가 필요합니다.)
  2. 두 개의 단일 문자 사이의 패턴을 추출하는 일반적인 절차 (가설 x및 여기)는 다음과 같습니다.y

    sed의 #^[^x]X##;s#y[^y]$##;s#y[^x]*x#,#g;'

    그건:

    • 첫 번째 ( ) ^앞의 선행 문자를 제거합니다 x.
    • $마지막 ( ) 뒤의 문자를 제거합니다 y.
    • y와 x 사이의 문자를 구분 기호( ,이 경우 쉼표())로 변환합니다.

모든 것을 한 번에:

$ sed 'H;$!d;x; s#<abc>#^A#g; s#</abc>#^B#g;' s#^[^^A]*^A##; s#^B[^^B]*$##; s#^B[^^A]*^A#,#g;' file
aaaa,bbbb,
cccc
dddd,eeee

grep

(GNU) grep을 사용하여 수행할 수 있지만 올바른 위치에 쉼표만 입력하려면 붙여넣기의 도움이 필요합니다.

$ grep -ozP '(?s)<abc>\K.*?(?=</abc>)' file | paste -zsd ','; echo
aaaa,bbbb,
cccc
dddd,eeee

관련 정보