다음과 같은 연속된 줄이 포함된 파일이 있습니다.
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를 사용하여 일치하는 패턴과 일치하는 줄을 인쇄하세요.