여러 줄 파일을 여러 줄 파일로 변환

여러 줄 파일을 여러 줄 파일로 변환

제가 변환하려는 파일은 다음과 같습니다.

john doe  
555-666-333  
[email protected]  
die  
jane doe  
Beverly Hills
444-333-111  
[email protected]  
die  

결과 파일이 다음과 같기를 원합니다.

john doe,555-666-333,[email protected]  
jane doe,Beverly Hills,444-333-111,[email protected]

단어가 die파일에 있으며 위에 표시된 대로 출력에 표시되지 않도록 이 단어를 사용하여 줄을 구분하고 싶습니다.

편집하다
파일 형식을 변경했습니다. 전자 형식은 단어 수가 단어마다 다를 수 있다는 사실을 고려하지 않습니다 die.

답변1

$ awk -v OFS=',' '/^die$/ { print substr(lines,2); lines=""; next } { lines=lines OFS $0 }' file
john doe,555-666-333,[email protected]
jane doe,Beverly Hills,444-333-111,[email protected]

쉼표가 포함된 데이터에도 동일한 내용이 적용됩니다(아래 답변의 끝 부분 참조). 데이터에 쉼표가 포함된 경우 다음을 사용할 수 있습니다.

awk -v OFS=',' '
    /^die$/ { print substr(lines,2); lines=""; next }
    /,/     { $0=sprintf("\"%s\"", $0 ) }
            { lines=lines OFS $0 }' file

이 코드는 (쉼표) lines로 구분된 문자열을 작성합니다. 한 줄에 OFS단어 자체가 있으면 해당 문자열을 출력합니다. 이 호출은 레코드의 첫 번째 필드가 문자열에 추가될 때 줄 앞에 추가된 쉼표를 제거합니다. 쉼표가 있는 줄은 아래 코드와 동일한 방식으로 처리됩니다.dielinessubstr()

GNU awk또는 BSD를 사용하여 이 작업을 수행할 수도 있지만 mawkBSD는 사용할 수 없습니다.awk

mawk -v RS='\ndie\n' -v FS='\n' -v ORS='\n' -v OFS=',' '{$1=$1;print}' file

쉼표가 포함된 데이터에 대해서는 따옴표 붙은 필드를 생성하지 않습니다.

출력 전에 (출력 필드 구분자) 및 (출력 레코드 구분자) 변수를 기반으로 레코드를 $1=$1강제로 재구성합니다 awk.OFSORS


질문을 업데이트하기 전에 대답하십시오:

paste -d, - - - - <file

이것은 생산할 것입니다

john doe,555-666-333,[email protected],die
jane doe,444-333-111,[email protected],die

이 줄을 제거하려면 die(완전히 불필요함):

paste -d, - - - - <file | cut -d, -f 1-3

위 방법은 원본 데이터에 쉼표가 포함되어 있지 않은 경우에 작동합니다.

die처음부터 행을 필터링 할 수도 있습니다 .

sed '/^die$/d' file | paste -d, - - -

이는 원본 데이터에 쉼표가 포함된 경우에도 작동합니다.

데이터에 쉼표가 포함된 경우 이를 전처리하여 줄 주위에 따옴표를 추가해야 할 수도 있습니다.

awk '/^die$/ { next } /,/ { $0=sprintf("\"%s\"", $0 ) } 1' file | paste -d, - - -

주어진 파일

john doe
555-666-333
[email protected]
die
jane doe
444-333-111
[email protected]
die
Me, myself and I
000-000-000
[email protected]

마지막 명령은 생성됩니다

john doe,555-666-333,[email protected]
jane doe,444-333-111,[email protected]
"Me, myself and I",000-000-000,[email protected]

답변2

다음과 같은 관용구를 사용하여 이를 수행할 수 있습니다 awk.

$ awk '$1=$1' RS='.die\n' OFS="," FS='\n' file1
john doe,555-666-333,[email protected]
jane doe,Beverly Hills,444-333-111,[email protected]

위에서는 기록 구분 기호를 파일에서 개인 세부 정보를 구분하는 데 사용되는 항목 으로 awk정의했습니다 .RSdie

$1=$1출력 필드 구분 기호로 ","를 사용하여 awk가 입력 필드를 다시 계산하고 인쇄하도록 강제합니다.OFS

추신: 가능한 문자 제거를 \r호출하는 데 사용하는 것처럼 파일 끝에 문제가 있다고 의심되는 경우 :tr\rtr -d '\r' file1 |awk .....

그런데 sed를 다음과 같이 사용할 수도 있습니다.

$ sed -z 's/\n/,/g; s/,die,/\n/g'

이는 sed를 속여 널 문자를 레코드 구분 기호로 사용함으로써 awk와 동일한 출력을 생성합니다.

입력 파일에 실제 널 문자가 없으면 sed는 전체 입력 파일을 하나의 큰 레코드 == 하나의 큰 줄로 처리합니다.

답변3

이는 "sed" 편집기를 사용하여 POSIX 방식으로 수행할 수 있습니다.

sed -e '
    :a
       $q;N;y/\n/,/
       s/,die$//;t
    ba
' input_file

방법:

  • 루프를 설정하고 패턴 공간에 다음 줄을 추가합니다.
    • 질소주문하다
  • 개행 문자를 쉼표로 변경하고 ",die"를 제거해 보세요.
    • 예/// 에스///주문하다
  • 성공하면 모든 것이 준비된 것이므로 추가 처리가 필요하지 않습니다.
    • 레이블이 없는 명령
  • 그렇지 않으면, 우리가 끝내고 그만둘 경우를 대비해 돌아가서 더 많은 것을 얻으십시오.
    • 그리고 주문하다.

이 목적으로 Perl을 사용할 수도 있습니다.

perl -lne '
    push @A, $_ unless /^die$/;
    print join ",", splice @A if /^die$/ || eof;
' input_file

"주사위" 행이 보일 때까지 배열에 행을 축적합니다. 이 시점에서 우리는 쉼표를 통해 배열 내용을 연결합니다(또한 배열을 지웁니다).

파일을 읽은 다음 Perl을 호출하여 결과를 얻을 수도 있습니다.

perl -lF'/^die\n/m' -0777nae 'print join ",", split /\n/ for @F' input_file
  • -에프'/^die\n/m'은 파일을 정규식 BOL 다이의 줄 바꿈이 뒤따르는 문자열로 분할합니다.
  • -0777은 빨기 소리를 냅니다.-N라인 자동 인쇄 및-ㅏ을 기반으로 할 것이다-에프값.

관련 정보