sed를 사용하여 패턴이 있는 줄을 다음 줄에 연결하는 방법은 무엇입니까?

sed를 사용하여 패턴이 있는 줄을 다음 줄에 연결하는 방법은 무엇입니까?

포럼에서 해당 사례를 찾을 수 없어서 질문했습니다.

입력 파일은 다음과 같습니다.

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 로 시작하면 moduleprint뒤에 \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위의 방법을 사용하여 열 간격을 지정하십시오.

https://docs.raku.org
https://raku.org

관련 정보