sed를 사용하여 두 줄의 문자열 편집

sed를 사용하여 두 줄의 문자열 편집

다음과 같은 연속된 줄이 포함된 파일이 있습니다.

macroa{abc def 123 ghi}
macrob{abc 123 xyz}

Macrob의 첫 번째 문자열이 Macroa와 동일한지 확인하고 제거하고 싶습니다. 결과는 다음과 같습니다.

macroa{abc def 123 ghi}
macrob{123 xyz}

전체 파일 방식을 사용하고 있습니다여기내 명령은

sed -e '1h;2,$H;$!d;g' -e 's/\(macroa{\([a-z]*\) [^\n]*\)\n\(macrob{\)\2 /\1\n\3/g' in > out

그러나 이것은 작동하지 않습니다. 내가 뭘 잘못했나요? 감사합니다.

답변1

GNU로 스크립트를 테스트했는데 sed예상한 결과가 나왔습니다. 그러나 이는 표준에 정의되어 있지 않은 내부적 으로 대체하여 사용하기 sed때문에 다른 버전 으로 이식할 수 없습니다 .\n[]

이를 대체하여 사용하면 쉽게 피할 수 있습니다.

sed -e '1h;2,$H;$!d;g' -e 's/\(macroa{\([a-z]*\) [^\n]*\)\(\nmacrob{\)\2 /\1\3/g'

표현식에서 이것을 사용하려면 []트릭을 사용하면 됩니다. 이 y명령을 사용하여 개행 문자를 일반 문자로 바꾼 다음 다시 변경합니다. 이 경우에는 다음을 사용합니다 |.

sed -e '1h;2,$H;$!d;g' -e 'y/\n|/|\n/;s/\(macroa{\([a-z]*\) [^|]*\)\(|macrob{\)\2 /\1\3/g;y/\n|/|\n/'

이것은 일반적인 해결책이지만 보기 흉하다고 생각합니다. 대부분의 경우 개행 문자를 제외한 모든 코드에는 인쇄 가능한 문자가 포함되어 있으므로 [^\n]대신 쓸 수 있습니다 .[[:print:]]

sed 'H;1h;$!d;g;s/\(macroa{\([a-z]*\) [[:print:]]*\)\n\(macrob{\)\2 /\1\n\3/g'

(이니셜도 1h;2,$H로 줄였습니다 H;1h.)

don_crissti의 의견을 고려하여 이러한 종류의 문제를 해결하는 일반적인 방법은 루프를 수행하는 것이라고 덧붙였습니다 N;P;D. 항상 N확장 라인을 추가하고 두 라인을 함께 처리한 다음 P첫 번째 라인을 인쇄하고 D패턴 공간에서 제거하여 두 번째 라인을 계속합니다.

sed 'N;s/\(macroa{\)\([a-z]* \)\(.*\nmacrob{\)\2/\1\2\3/;P;D'

답변2

awk대신 사용할 수 있는 경우sed

$ awk -F'[{ ]' 'c && c-- && $1=="macrob" && $2==s{sub(s" ", "")}
                $1=="macroa"{c=1; s=$2} 1' ip.txt
macroa{abc def 123 ghi}
macrob{123 xyz}
  • -F'[{ ]'{필드 구분 기호로 또는 공백 문자 사용
  • $1=="macroa"{c=1; s=$2}첫 번째 필드가 macroa초기화 카운터를 사용 1하고 두 번째 필드를 변수에 저장합니다. 카운터는 다음 중 어떤 줄을 확인해야 하는지 결정합니다.
  • c && c--이는 카운터가 0이 아닌 한 참입니다. c=1이 경우 카운터는 이것이 참일 때만 추가 조건에 관계없이 0으로 이동합니다 . 따라서 연속된 행만 일치합니다.
  • $1=="macrob" && $2==s필수 조건
    • sub(s" ", "")문자열 및 공백 문자 제거
  • 추가 자료:sed 또는 awk를 사용하여 일치하는 패턴과 일치하는 줄을 인쇄하세요.

관련 정보