여러 파일에서 특정 문자가 발견될 때마다 라인을 스트리밍합니다.

여러 파일에서 특정 문자가 발견될 때마다 라인을 스트리밍합니다.

다음은 한 줄로 변환하려는 파일의 예입니다.

-
Jun 6th
something2
09:00
some text blah blah
something1
Jun 6th
something1
09:00
some text xxx
something1

이 행을 csv와 같은 하나의 행으로 가져오려고 합니다. 예:

Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

답변1

다음 SED 문장을 시도해 볼 수 있습니다.

sed -ne '/^–/{g; /./!b; s/\n//; s/\n/, /g; p; z; h; b}; H' INPUTFILE

설명하다:

/^–/{                 -->  if line starts with char "–", then:
    g                 -->      copy hold space to pattern space
    /./!b             -->      empty line? restart cycle
    s/\n//            -->      get rid of first newline
    s/\n/, /g         -->      replace all other newlines by ", "
    p                 -->      print pattern space
    z                 -->      erase pattern space
    h                 -->      erase hold space
    b                 -->      start new cycle
    }
H                     -->  otherwise, append newline + pattern space to hold space

입력하다:


Jun 6th
something2
09:00
some text blah blah
some other thing2
Jun 7th
something1
10:30
some text xxx
some other thing1
Jun 9th
something3
12:15
some text yyy
some other thing3
Jun 8th
something4
07:05
some text zzz
some other thing4

산출:

Jun 6th, something2, 09:00, some text blah blah, some other thing2
Jun 7th, something1, 10:30, some text xxx, some other thing1
Jun 9th, something3, 12:15, some text yyy, some other thing3
Jun 8th, something4, 07:05, some text zzz, some other thing4

도움이 되길 바랍니다.

답변2

먼저, 데이터가 두 가지 유형의 대시 문자, 즉 ASCII 하이픈과 유니코드 대시(U+2013)로 구분된다는 점에 유의하는 것이 중요합니다.

Awk의 GNU 구현(GNU Awk)은 레코드 분리를 위한 정규식을 처리할 수 있습니다. 이것은 문장입니다:

$ gawk -v RS='\n?[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

data예제가 포함된 파일은 그대로 저장되어 있습니다.

선택적 개행 문자와 ASCII 대시 또는 유니코드 대시와 개행 문자와 일치하는 레코드 구분 정규식을 설정했습니다. 그런 다음 이러한 레코드의 필드 구분 기호는 개행 문자입니다. 출력 구분 기호는 쉼표와 공백입니다.

이 표현은 $1=$1두 가지 목적으로 사용됩니다. 필드를 다시 자신에게 할당하면 사용자 정의 필드 구분 기호 $0를 고려하여 레코드가 재구성됩니다 . OFS그런 다음 인쇄하면 됩니다. 데이터가 레코드 구분 기호로 시작하므로 초기에는 빈 레코드가 있습니다. 이 레코드의 경우 표현식은 $1 = $1공백 값을 할당하고 결과이므로 표현식은 부울 false이므로 레코드는 인쇄되지 않습니다.

\n패턴 에 선택적 선행 문자를 포함 하지 않은 경우 다음 개행 문자가 필드 구분 기호로 해석되므로 RS각 레코드는 추가 공백 필드로 끝나게 됩니다 . something1레코드 구분 기호의 일부로 마지막 필드 뒤에 개행 문자가 필요합니다. 파일이 레코드 구분 기호로 시작하고 앞에 줄 바꿈 문자가 오지 않으므로 선택 사항이어야 합니다. 그것 없이 우리는 이것을 얻습니다:

$ gawk -v RS='[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1,
Jun 6th, something1, 09:00, some text xxx, something1,

추가 빈 필드로 인해 추가 쉼표가 발생했습니다.

답변3

tr 및 sed 명령을 사용하여 이 작업을 수행할 수 있습니다.

$ tr '\n' ',' <input_file | sed 's/-,/\n/g' | sed 's/.$//'

Jun 6th,something2,09:00,some text blah blah,something1
Jun 6th,something1,09:00,some text xxx,something1

(두 번째 sed는 후행 쉼표를 제거합니다)

대시 구분 기호가 입력 파일에서 동일한지 확인해야 합니다. 이 코드를 테스트하기 위해 복사했을 때 그렇지 않았습니다.

답변4

something*입력에 따옴표나 쉼표가 있을 수 있고, 레코드에 줄 바꿈이 없고, some text*실제 레코드 구분 기호만 있는 유효한 CSV 출력을 원한다고 가정할 때 -잠재적인 솔루션을 테스트하기 위한 입력 파일은 다음과 같습니다.

$ cat file
-
Jun 6th
something2
09:00
"some "text" blah blah"
"something1"
-
Jun 6th
something1
09:00
some, text, xxx
something1
-

다음은 유효한 CSV 출력인 POSIX awk를 사용하는 솔루션입니다.

$ cat tst.awk
$1 == "-" {
    if ( NR > 1 ) {
        print ""
    }
    sep = ""
    next
}
/[",]/ {
    gsub(/^"|"$/,"")
    gsub(/"/,"\"\"")
    $0 = "\"" $0 "\""
}
{
    printf "%s%s", sep, $0
    sep = ","
}

$ awk -f tst.awk file
Jun 6th,something2,09:00,"some ""text"" blah blah","something1"
Jun 6th,something1,09:00,"some, text, xxx",something1

이것이 입력에 대해 원하는 출력이 아닌 경우 질문의 예제를 편집하여 ,입력에 s 및 s가 있는 경우를 처리하는 방법을 보여줍니다."

관련 정보