여러 줄이 포함된 파일이 있는데 모두 특정 패턴과 일치하면 연결하고 싶습니다.
다음을 사용하여 패턴에 맞는 줄을 찾고 다음 줄을 얻을 수 있다는 것을 알고 있습니다.
grep -E -A1 'Pattern' filename
하지만 다음 줄도 패턴과 일치하는지 어떻게 확인하고 두 줄을 어떻게 연결합니까?
예를 들어 다음과 같은 파일이 있습니다.
Hello
i
am
John
Smith
예시 패턴은 다음과 같습니다.
'^[A-Z][a-z]+'
따라서 이 경우에는 모두 대문자로 시작하는 줄을 병합하고 싶습니다.
내가 달성하려는 결과는 다음과 같습니다.
Hello
i
am
John Smith
답변1
/^[A-Z][a-z]+/{
:a
N
/\n[A-Z][a-z]+/{
s/\n/ /
b a
}
}
다른 이름으로 저장 join.sed
하고 실행하십시오 sed -Ef join.sed file
.
줄이 패턴과 일치하면 패턴 공간에 다음 줄을 추가하고 줄도 패턴과 일치하는 한 줄 바꿈을 공백으로 바꾸는 루프를 시작합니다.
GNU Sed의 경우 한 줄로 축소할 수 있습니다.
sed -E '/^[A-Z][a-z]+/{:a;N;/\n[A-Z][a-z]+/{s/\n/ /;b a}}' file
join.awk
또는 패턴이 다음과 같아야 하는 Awk 스크립트 p
:
{
if($0~p)c+=1
else c=0
printf "%s%s", (c>1 ? " " : ors), $0
ors=ORS
}
END{print ""}
구현하다: awk -f join.awk p='^[A-Z][a-z]+' file
.
답변2
sed
null 문자를 구분 기호( -z
) 로 사용합니다 .
$ sed -z 's/\([A-Z][a-z]\+\)\n\([A-Z][a-z]\+\)/\1 \2/'
Hello
i
am
John Smith
답변3
Raku(이전 Perl_6) 사용
raku -e 'given lines.join("\n") { S/ $<first>=[<upper><lower>+] \n $<last>=[<upper><lower>+] /$<first> $<last>/.put};'
입력 예:
Hello
i
am
John
Smith
goodbye
예제 출력:
Hello
i
am
John Smith
goodbye
위 내용은 Perl 계열의 언어인 Raku로 작성된 솔루션입니다. 데이터는 given
의 형태로 Raku로 전송되지만 lines
, Raku의 lines
입력 자동 잘라내기 루틴으로 인해 데이터가 join
줄바꿈됩니다. 다소 복잡해 보일 수 있지만 Raku의 lines
루틴이 데이터를 느리게 읽을 수 있다는 장점이 있습니다. 즉, 위의 코드는~해야 한다높은 메모리 효율성.
Raku는 친숙한 연산자(Raku에도 있음)와 동일하지는 않더라도 유사한 S///
"비파괴적" 연산자를 구현합니다. s///
자본 운영자에게는 S
이점이 있습니다."원래 문자열을 그대로 유지하고 $/(일치 변수) 대신 결과 문자열을 반환합니다."
연산자의 일치하는(왼쪽) 절반 내에서 S///
,명명된 캡처취업하세요. 정규식 엔진은 먼저 이를 검색 [<upper><lower>+]
하여 명명된 캡처에 할당한 $<first>
다음 하나(개행 문자)를 검색 \n
하고 마지막으로 다른 문자를 검색하여 [<upper><lower>+]
이번에는 명명된 캡처에 할당합니다 $<last>
. 마지막으로 연산자의 대체(오른쪽) 절반에서 S///
두 개의 명명된 캡처가 $<first> $<last>
왼쪽 일치를 대체하는 데 사용됩니다.그리고공간과아니요\n
사이에 줄이 끊어집니다.
동일한 작업을 수행하는 또 다른 방법은 다음과 같습니다. 코드에서는 명명된 캡처를 생략하고 대신 <(\n)>
일치 개체에서 캡처 태그 내의 콘텐츠를 제외한 모든 항목을 제거하는 캡처 태그를 사용합니다 <(…)>
. 그런 다음 바꾸기에서 공백 \n
으로 바꿉니다.
raku -e 'put S/ [<upper><lower>+] <(\n)> [<upper><lower>+] / / given lines.join("\n");'
[위 코드는 George\nHerbert\nWalker\nBush
4행을 3행으로만 축소합니다( George Herbert\nWalker\nBush
). 행에서 연속된 항목을 모두 반환하려면 [<upper><lower>+]
이 질문을 게시해 주시기 바랍니다.]
https://docs.raku.org/언어/regexes#S///_non-breaking_substitution
https://docs.raku.org/언어/regexes#index-entry-regex__Named_captures-Named_captures
https://raku.org