2014-08-28 2 views
0

해당 ID를 기반으로 bibtex 파일 에있는 항목의 첫 번째 항목을 삭제하고 싶습니다. 예를 들어, 우리는이 파일이 있다고 가정 해 봅시다 :sed를 사용하여 bibtex 항목의 첫 번째 발생을 삭제하는 방법은 무엇입니까?

@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

을 그리고 ID1을 포함하는 첫 번째 항목을 삭제하려면, 그래서 을하고자하는 출력은 다음과 같습니다

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

를 내가 원하는 자동으로 sed을 사용하여이를 수행하는 방법. 지금까지는 다음과 같습니다.

sed '/^@.*{id1/, /}/d' input_file 

그러나 파일의 모든 항목이 삭제됩니다. 첫 번째 것을 삭제하는 방법을 찾도록 도와 줄 수 있습니까?

답변

3

이 당신을 위해 작동 할 수

awk -v RS= -v ORS='\n\n' '!/@inproceedings{id1/' f 
@inproceedings{id2, 
    author = "", 
    title = "", 
     ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
     ... 
} 
+0

쿨! 그것은 효과가 있지만 그것이 무엇을하는지 이해하지 못합니다. 어떻게 작동하는지 더 자세히 설명해 주시겠습니까? 나는 또한 Google에있는 세부 사항을 찾는 것을 시도 할 것이다.. 고마워! –

+1

@ThanasisPetsas 편집을 참조하십시오. – potong

+0

설명 주셔서 감사합니다. 나는이 기록을 모르고 있었다. .. 그들은 매우 도움이되는 것처럼 보인다! –

1

AWK 사용자 정의 RS (레코드 분리)이 작업을 수행 할 수있는 작업은 다음과 같습니다 (/start/,/end/ action)

+0

"id1"을 처음으로 검색하는 대신 검색합니다. –

+0

예 OP 만 검색 할 수 있지만 OP는 첫 번째 항목을 제거하려고합니다. 내 대답에 그것을 추가하자. – anubhava

+0

오른쪽! 나는이 질문에 언급 한 것처럼 이드를 기반으로 무언가를 삭제하고 싶다. –

1
sed '/^@inproceedings{id1,/,/}/ d' YourFile 

이 섹션의 각 줄을 삭제 (GNU는 나오지도) :

sed 'x;/./{x;b};x;/^@.*{id1/,/}/{/}/h;d}' file 

첫 번째 발생이 삭제 된 후 보류 공간에 플래그를 설정합니다. 플래그가 설정된 경우 파일 끝까지 추가 라인을 무시하십시오.

sed 명령을 쓸 때 사용할 수있는 두 개의 레지스터가 있습니다. Sed는 패턴 라인 (PS)에 현재 라인 (줄 바꿈 제외)을 배치하고 두 번째 레지스터는 대기 공간 (HS)을 호출합니다. x은 HS에 대한 PS를 교환하고 h은 PS를 HS에 복사합니다. sed 한 줄 스크립트는 HS에 대한 PS를 바꿔 HS에 문자 /./이 있는지 확인합니다.이 조건이 참이면 PS에 대한 HS를 다시 채우고 보석금을냅니다. 조건이 참이 아닌 경우 HS는 PS에 대해 재결정되고 이후 명령이 실행됩니다. 범위 조건은 /^@.*{id1/,/}/으로 검색되며, 두 줄 사이의 모든 줄을 포함합니다. 찾으면이 줄이 삭제되지만 현재 줄이 끝 조건 인 것으로 발견되면이 줄이 HS에 복사됩니다. /}/h. 이제 후속 행은 파일의 끝까지 무시됩니다.

+0

그러나 ** id1 **이 (가)있는 항목이 모두 'inproceedings'인 경우 두 항목 모두 지워지지만 첫 번째 항목 만 삭제하려고합니다. –

+0

정확함. 귀하의 샘플을 적응, 나는 코드를 적용하려고합니다. 나는 Potong이 이미이 발언을 포함하여 더 좋은 코드를 추가 한 것을 보았습니다 :-) – NeronLeVelu

1

sed는 한 줄에 간단한 대체를위한 훌륭한 도구이지만 다른 모든 텍스트 조작에는 awk를 사용해야합니다.

$ awk -v type="inproceedings" -v id="id1" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

.

$ awk -v type="inproceedings" -v id="id2" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

.

$ awk -v type="misc" -v id="id1" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

하고 대신 일치하지 않는 것과의 일치하는 블록을 선택하려면, 단지 조건의 시작 부분에 ! 제거하기.

여러 행의 코드 블록 (즉, -n과 함께 s, g 및 p를 제외한 모든 문자)을 조작하는 모든 sed 언어 구문은 awk가 발명 된 1970 년대 중반에 쓸모 없게되었습니다. 그들을 필요로하지 않을 것이다.Arnold Robbins의 Effective Awk Programming, Third Edition을 읽어보십시오.

+1

대단히 감사합니다! 이 솔루션도 훌륭합니다. 그러나'sed'에 기초한 바람직한 해결책을 요구하면서 나는 potong의 대답을 받아 들였다. 그럼에도 불구하고'awk'는 놀라운 명령/언어입니다! 도서 제안을 주셔서 감사합니다. –

+0

당신을 진심으로 환영합니다. 당신이 물을 때부터 sed 기반의 솔루션을 받아들이는 것이 합리적입니다. 물론 그것을 실제로 사용하지 마라. 그것은 듣기 좋은 노래로 이끌 것이다. 그것은 작동하지만, 나는 그것이 무엇을하고 있는지 이해하지 못하고 단지 가장 단순한 것조차도 다르게 또는 추가적으로 수정할 것을 권합니다. 블록에서'author'가 빠졌을 때 stderr에 메시지를 출력하십시오 :-). –

관련 문제