구분 기호로 줄 분할

구분 기호로 줄 분할

다음과 같이 공백으로 구분된 텍스트 파일이 있습니다.

text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3,id4 text4c text5c
text1d text2d id5,id6,id7 text4d,text4di text5d

파일 길이는 약 150만 줄입니다.

일부 행에는 예제의 행 3과 같이 쉼표로 구분된 두 개의 ID가 있습니다. id3이로 인해 파일을 다른 파일(id가 또는 일 수 있음)과 연결하려고 할 때 문제가 발생합니다 id4.

3열에 쉼표가 있는 모든 인스턴스를 찾아 양쪽의 내용을 별도의 줄로 구분하고 싶습니다. 예를 들어 위 파일은 다음과 같습니다.

text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

일부 행에는 쉼표로 구분된 ID가 3개 이상 포함되어 있습니다. 쉼표는 다른 열에 나타날 수 있지만 그대로 유지되어야 합니다. 순서는 중요하지 않습니다. 예를 들어 id3 또는 id4가 파일에서 먼저 나오는지 여부입니다.

저는 피어링에 대한 경험이 상당히 없으며 awk이것이 sed해당 작업에 가장 적합한 도구라고 생각합니다.

누구든지 올바른 방향으로 나를 가리킬 수 있습니까?

답변1

$ awk 'split($3,f,/,/)>1{for (i=1; i in f; i++) {$3=f[i]; print} next } 1' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

위의 내용은 $3에 나열된 ID의 순서를 유지합니다. 원하지 않는 경우 로 for (i in f)대체 할 수 있습니다 for (i=1; i in f; i++).

Split()이 1보다 큰 값을 반환하는 경우 무조건 할당을 수행하는 것보다 $3를 할당하는 루프 블록을 수행하는 것이 더 효율적입니다. 왜냐하면 필드에 대한 각 할당은 awk가 현재 레코드를 다시 작성하도록 강제하고 모든 FS를 OFS로 대체하기 때문입니다. .

답변2

선이 분할되는 순서는 중요하지 않으므로 다음을 사용하여 분할할 수 있습니다 awk.

$ awk '{ split($3,a,","); for (i in a) { $3 = a[i]; print } }' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

각 행에 대해 세 번째 필드를 쉼표에 배치하여 배열을 만듭니다 a. 필드에 쉼표가 없으면 배열에는 단일 요소만 포함될 수 있습니다.

그런 다음 코드는 배열의 인덱스를 반복하고 a(배열을 구현한 방법에 따라 어떤 순서로든 수행될 수 있음 awk) 세 번째 필드를 배열의 현재 요소로 설정하여 수정한 a다음 전체를 인쇄합니다. (수정될 수도 있음) 기록.

답변3

또 다른 접근 방식은 다음과 같습니다.

cat fun.awk

$3~/^id[0-9]+,/ {
    split($3, store, ",");
    for (i = 1; i in  store; i++)
        print $1, $2, store[i], $4, $5

    next
}

{ print $0 }

세 번째 열에 쉼표( $3~/^id[0-9]+,/)가 포함되어 있으면 이를 분할하고 각 열에 대해 한 줄을 인쇄하고 다음 루프로 이동합니다. 그렇지 않으면 전체 줄을 인쇄합니다( $0).

관련 정보