연속된 문자열 사이의 텍스트 제거

연속된 문자열 사이의 텍스트 제거

텍스트 파일에서 지정된 두 문자열 사이의 모든 텍스트를 제거해야 합니다. 문자열은 다른 줄에 있을 수 있습니다. 예를 들어 다음 텍스트 파일에서

@article{ginsberg_lifespan_2018,
    title = {On the lifespan of three-dimensional abstract gravity water waves with vorticity},
    abstract = {test1
test2  abstract {NS}

test3},
    language = {en},
    urldate = {2018-12-05},
    author = {Ginsberg, Daniel},
    month = dec,
    year = {2018}
}

@article{higaki_two-dimensional_2017,
    title = {On the two-dimensional steady {Navier}-{Stokes} equations related to flows around a rotating obstacle},
    abstract = {We study the two-dimensional stationary Navier-Stokes equations with rotating effect in the whole space. The unique existence and the asymptotics of solutions are obtained without the smallness assumption on the rotation parameter.},
    journal = {arXiv:1703.07372 [math]},
    author = {Higaki, Mitsuo and Maekawa, Yasunori and Nakahara, Yuu},
    month = mar,
    year = {2017},
    note = {arXiv: 1703.07372},
    keywords = {Mathematics - Analysis of PDEs}
}

이 문자열을 포함하여 항상 줄 끝에 있는 abstract =와 a 사이의 모든 항목을 제거하고 싶습니다 . },즉, 다음과 같은 출력을 원합니다.

@article{ginsberg_lifespan_2018,
    title = {On the lifespan of three-dimensional abstract gravity water waves with vorticity},
    language = {en},
    urldate = {2018-12-05},
    author = {Ginsberg, Daniel},
    month = dec,
    year = {2018}
}

@article{higaki_two-dimensional_2017,
    title = {On the two-dimensional steady {Navier}-{Stokes} equations related to flows around a rotating obstacle},
    journal = {arXiv:1703.07372 [math]},
    author = {Higaki, Mitsuo and Maekawa, Yasunori and Nakahara, Yuu},
    month = mar,
    year = {2017},
    note = {arXiv: 1703.07372},
    keywords = {Mathematics - Analysis of PDEs}
}

이런 유형의 질문이 있다는 것을 알고 게시된 솔루션을 시도해 보았습니다. 예를 들어, 나는

perl -0777 -pe 's/abstract = .*},\n/\n/gs'

abstract =그러나 이렇게 하면 연속되는 항목이 아닌 첫 번째 항목과 마지막 항목 사이의 텍스트가 제거됩니다 },. 이게 내가 얻은 거야

@article{ginsberg_lifespan_2018,
    title = {On the lifespan of three-dimensional gravity water waves with vorticity},

    keywords = {Mathematics - Analysis of PDEs}
}

원하는 결과를 얻으려면 이 명령을 어떻게 수정해야 합니까?

답변1

$ sed '/abstract = .*},$/d; /abstract = /,/},$/d' <file
@article{ginsberg_lifespan_2018,
    title = {On the lifespan of three-dimensional abstract gravity water waves with vorticity},
    language = {en},
    urldate = {2018-12-05},
    author = {Ginsberg, Daniel},
    month = dec,
    year = {2018}
}

@article{higaki_two-dimensional_2017,
    title = {On the two-dimensional steady {Navier}-{Stokes} equations related to flows around a rotating obstacle},
    journal = {arXiv:1703.07372 [math]},
    author = {Higaki, Mitsuo and Maekawa, Yasunori and Nakahara, Yuu},
    month = mar,
    year = {2017},
    note = {arXiv: 1703.07372},
    keywords = {Mathematics - Analysis of PDEs}
}

먼저 전체 한 줄 abstract항목을 제거하려고 시도하고, 그래도 작동하지 않으면 여러 줄 항목을 제거하려고 시도합니다 abstract. 여러 줄 항목은 abstract =포함 줄부터 로 끝나는 다음 줄까지의 줄 집합 입니다 },.

주석이 달린 sed스크립트:

/abstract = .*},$/d    # delete complete abstract line, skip to next input line
/abstract = /,/},$/d   # delete multi-line abstract entry

예를 들어 시작 문자열을 더 구체적으로 지정해야 하는 경우 이러한 표현식의 일부를 ^[[:blank:]]*abstract대신 사용할 수 있습니다. 이 줄 앞에는 공백이나 탭만 abstract허용됩니다 .abstract =

답변2

예를 들어 sed의 솔루션은 각 시작 및 끝 문자열을 다음으로 변환하는 것입니다.하나문자이므로 정규식을 사용하여 문자를 방지(부정)할 수 있습니다 [^…].

문자로 변환합니다( %(시작) 및 #(끝)이 파일에 나타날 수 없다고 가정하고 나중에 자세히 설명합니다):

<<<infile sed 's/abstract =/%/g; s/},\n/#/g'

그런 다음 첫 번째 항목에서 선택(및 삭제)할 수 있습니다.시작( %)특징처음으로( #) 문자 뒤:

sed 's/%[^#]*#//g'

[^#]게임을 플레이하는 데 필요한욕심이 없다.

일부 구분 문자가 여전히 존재할 수 있으므로 이를 복원해야 합니다.

sed 's/%/abstract =/g; s/#/},\n/g'    # assuming GNU sed.

물론 패턴이 다른 줄에 나타날 수도 있으므로 위의 내용을 전체 파일에 모두 적용해야 합니다. 따라서 예약된 공간에 전체 파일을 캡처합니다.

sed 'H;1h;$!d;g;'

전체 명령줄에서 다음을 수행합니다.

 <infile sed 'H;1h;$!d;g;  s/abstract =/%/g; s/},\n/#/g;
                           s/%[^#]*#//g ;
                           s/%/abstract =/g; s/#/},\n/g'

선택한 문자가 입력 파일에 존재할 가능성이 있는 경우 텍스트 파일에 존재하지 않는 다른 명시적 구분 기호를 선택할 수 있습니다.

ASCII에서 SOH(헤더 시작) 및 STX(텍스트 시작)로 01알려진 값이 있는 문자(바이트) 02는 "제어 문자"이며 텍스트 파일에서는 매우 드뭅니다. 이를 사용하려면 쉘 스크립트를 작성하는 것이 좋습니다.

 #!/bin/bash
 start=$'\1'
 end=$'\2'
 startpattern='abstract ='
 endpattern=$'},\\\n'         # The newline needs a `\` for sed to work.

 sed 'H;1h;$!d;g;
      s/'"$startpattern"'/'"$start"'/g;
      s/'"$endpattern"'/'"$end"'/g;
      s/'"$start"'[^'"$end"']*'"$end"'//g;
      s/'"$start"'/'"$startpattern"'/g;
      s/'"$end"'/'"$endpattern"'/g'  <infile

답변3

당신 말이 맞습니다. 여기에서는 이와 같은 질문이 셀 수 없이 많이 제기되었습니다. 얼마나 멀리 갈 것인가?

sed '/abstract.*{/ {:L; /}/{d; b;}; N; bL; }' file

이해합니다? 일치 후에 abstract는 필요한 경우 찾을 때까지 반복됩니다 }.

편집하다:수정된 요청 허용:

sed '/abstract.*{/ {:L; /},$/{d; b;}; N; bL; }' file

답변4

Perl 코드가 거의 완성되었습니다. 몇 가지만 수정하면 됩니다.

 perl -0777pe 's/abstract = .*?\},\n/\n/msg'

/s 플래그는 .를 개행과 일치시키고 .*?를 비탐욕적으로 만듭니다.

관련 정보