![sed를 사용하여 패턴이 있는 줄을 다음 줄에 연결하는 방법은 무엇입니까?](https://linux55.com/image/144697/sed%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%ED%8C%A8%ED%84%B4%EC%9D%B4%20%EC%9E%88%EB%8A%94%20%EC%A4%84%EC%9D%84%20%EB%8B%A4%EC%9D%8C%20%EC%A4%84%EC%97%90%20%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
포럼에서 해당 사례를 찾을 수 없어서 질문했습니다.
입력 파일은 다음과 같습니다.
module
x(a,b,c)
module
y(d,e,f,
g,h,i)
module
z(j,k,l)
출력 파일은 다음과 같아야 합니다.
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
답변1
당신이 원하는 것은 module
이 행을 다음 행과 연결하는 것입니다.
사용 sed
:
$ sed '/^module/N;s/\n//' file
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
데이터를 그대로 복사해서 붙여넣는 경우이며, 각 줄 끝에 공백을 둡니다.
이 sed
명령은 읽은 대로 각 줄을 인쇄하지만 문자열로 시작하는 줄을 만나면 module
다음 줄 사이에 삽입된 개행 문자를 추가합니다(이렇게 합니다 N
). 결과를 인쇄하기 전에 교체하여 개행을 제거합니다.
데이터에 후행 공백이 없으면 다음을 사용하십시오.
$ sed '/^module/N;s/\n/ /' file
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
원하는 경우를 대비하여(입력 줄 끝에 공백이 없다고 가정):
$ sed -e '/^module/bpp' -e 'H;$bpp' -e 'd' \
-e ':pp' -e 'x;/^$/d;s/\n/ /g' file
module x(a,b,c)
module y(d,e,f, g,h,i)
module z(j,k,l)
주석이 달린 sed
스크립트:
/^module/ b print_previous; # print previous record
H; # append this line to hold space
$ b print_previous; # print previous (last) record
d; # end processing this line
:print_previous; # prints a record accumulated in the hold space
x; # swap in the hold space
/^$/ d; # if line is empty, delete it
s/\n/ /g; # replace embedded newlines by spaces
# (implicit print)
보상 ed
내용:
$ printf '%s\n' 'g/^module/ j' ,p Q | ed -s file
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
위의 코드는 문자열에서 시작하는 모든 줄을 다음 줄과 module
연결합니다 .
$ printf '%s\n' 'v/^module/ -,.j' ,p Q | ed -s file
module x(a,b,c)
module y(d,e,f, g,h,i)
module z(j,k,l)
위의 줄을 연결하세요.아니요module
문자열로 시작더 일찍철사.
답변2
awk를 사용하세요:
~ awk '/^module/ {l = $0; getline; printf "%s", l} 1' input-file
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
로 시작하는 각 줄에 대해 module
줄을 에 저장하고 l
다음 줄( getline
)로 이동한 후 저장된 줄을 인쇄합니다(개행 없이). 그런 다음 각 줄을 인쇄하십시오.
답변3
또 다른 옵션: ed
스크립트를 생성하세요!
먼저 필요한 연결 수를 미리 계산한 다음 특정 수의 ed
검색 및 조인 명령을 생성하고 최종 저장 및 종료와 함께 다음으로 파이프합니다 ed
.
#!/bin/bash
n=$(grep -c '^module *$' input)
{
for((i=1; i <= n; i++))
do
printf '/^module *$/\n.,+1j\n'
done
echo w
echo q
} | ed -s input >/dev/null
답변4
사용행복하다(이전 Perl_6)
~$ raku -ne '/^module/ ?? (print "$_\t"; put get) !! .put;' file
또는:
~$ raku -ne '/^module/ ?? (put join "\t", $_, lines[0]) !! .put;' file
awk
위의 Raku의 답변은 @muru의 훌륭한 답변과 유사합니다. Raku에서는 삼항 연산자의 철자를 사용합니다.시험 ??
진짜 !!
잘못된. 이 -ne
플래그는 자동으로 인쇄하지 않고 파일을 한 줄씩 읽습니다.
줄이 ed 로 시작하면 module
그 print
뒤에 \t
탭 문자가 옵니다(모든 열 구분 기호로 대체 가능). 그런 다음 (첫 번째 예에서) 코드는 get
다음 줄과 그 put
내용을 나타냅니다. 두 번째 예에서는 $_
테마 변수를 인쇄 하고 다음 줄을 line[0]
결합한 \t
후 종료합니다 put
. 일치하는 항목이 없으면 module
(예: "False") 해당 줄이 종료됩니다 put
.
입력 예(줄 끝이 정리됨):
module
x(a,b,c)
module
y(d,e,f,
g,h,i)
module
z(j,k,l)
출력 예(탭으로 구분된 열):
module x(a,b,c)
module y(d,e,f,
g,h,i)
module z(j,k,l)
OP의 입력 텍스트에는 후행 공백이 포함되어 있으므로 원래 입력을 사용하는 것은 괜찮을 수 있지만 연결되는 다른 예제 텍스트 파일에는 후행 공백이 포함되지 않을 수 있으며, 이 경우 "열"이 함께 실행됩니다. 따라서 \t
위의 방법을 사용하여 열 간격을 지정하십시오.