일치하는 패턴에서 n번째 줄 바꾸기

일치하는 패턴에서 n번째 줄 바꾸기

다음 텍스트 파일이 있습니다.

banana
apple
juice
mango
something

나는 패턴을 검색 중이며 juice일치하는 패턴에서 두 번째 줄을 역순으로(즉, 일치하는 패턴 위의 2줄) 찾아서 로 바꾸고 싶습니다 coconut.

예상 출력:

coconut
apple
juice
mango
something

다음과 같이 시도했지만 위의 두 줄만 삭제되고 내가 찾고 있는 정확한 줄은 삭제되지 않습니다.

tac foo.txt |sed '/juice/I,+2 d' |tac
mango
something

위의 스크립트를 조정하면 작업이 수행될 것이라고 생각하지만 확실하지 않습니다.

참고: 일치 항목이 다시 발생하지 않으며 정확하게 일치할 필요도 없습니다(즉, 일치 항목을 긴 줄에서도 찾을 수 있음). 일치 항목은 대소문자를 구분해야 합니다.

답변1

괜찮다 면 ed스트림이 아닌 파일을 편집해야 하며 다음 중 하나만 편집해야 합니다  juice.

$ more <<-EOF | ed -s ./tmp.txt
	/juice/
	-2
	c
	coconut
	.
	w
	q
EOF
$

줄을 찾아서 두 줄 위로 올라가서 change, write,  quit를 하세요.


@d-ben-knoble이 의견에서 제안한 훨씬 더 컴팩트한 변형입니다.

$ printf '%s\n' '/^juice$/-2s/.*/coconut/' w q | ed -s ./tmp.txt

답변2

귀하의 접근 방식에 따라

tac file|sed '/juice/{n;n;s/.*/coconut/}'|tac
  • /juice/와 라인과 일치합니다 juice.
  • n;n;현재 줄과 다음 줄을 인쇄합니다.
  • s/.*/coconut/대체를 해줍니다.

분명히 GNU sed가 있으므로 -z전체 파일을 메모리로 가져오고 juice 위의 두 번째 줄을 직접 편집하는 데 사용할 수도 있습니다.

sed -rz 's/[^\n]*(\n[^\n]*\n[^\n]*juice)/coconut\1/' file

[^\n]"개행 문자가 아님"을 의미하며 괄호는 역참조 ()에 의해 재생된 그룹을 캡처합니다 .\1

답변3

$ tac file | awk 'c&&!(--c){$0="coconut"} /juice/{c=2} 1' | tac
coconut
apple
juice
mango
something

답변4

다음은 또 다른 awk접근 방식입니다. 이번에는 이중 전달 방법입니다.

awk 'NR==FNR&&/juice/{m=FNR} NR>FNR&&FNR==m-2{$0="coconut"} (NR>FNR)' file file
  • 우리는 파일을 지정합니다두 번두 번 처리되도록 명령줄 인수로 사용합니다.
  • 첫 번째 패스( FNR파일별 라인 카운터는 NR전역 라인 카운터와 같음)에서는 검색 패턴이 juice발생하는 라인을 간단히 식별하고 이를 변수에 저장합니다 m.
  • 두 번째 패스에서는 줄 번호를 m-2대체 텍스트로 설정합니다 coconut.
  • 일반적으로 모든 수정 사항을 포함하여 행을 인쇄하지만 두 번째 단계(조건이 NR>FNR"true"로 평가되는 경우)에서만 인쇄합니다.

GNU가 있는 경우 awk(일부 다른 awk구현에서도 이를 지원함) 다음 명령을 사용하여 일치 항목이 발견되자마자 첫 번째 단계를 중단하여 프로세스 속도를 약간 높일 수 있습니다 nextfile.

awk 'NR==FNR&&/juice/{m=FNR;nextfile} NR>FNR&&FNR==m-2{$0="coconut"} (NR>FNR)' file file

관련 정보