tsv 파일에서 큰따옴표로 묶인 열 안의 개행 문자를 제거하는 방법은 무엇입니까?

tsv 파일에서 큰따옴표로 묶인 열 안의 개행 문자를 제거하는 방법은 무엇입니까?

행에 "THIS CONTAIN NEWLINE"이 있어야 합니다(열 2와 4에서 줄 바꿈을 제거해야 함).

"column1"   "column2"          "column3"    "column4"           " column5"
"DATA"       "THIS                 "DATA"   "THIS                "DATA"
             CONTAIN NEWLINE"                 CONTAIN NEWLINE"

예상 출력:

"column1"   "column2"                "column3"  "column4"                " column5"
"DATA"      "THIS CONTAIN NEWLINE"    "DATA"    "THIS CONTAIN NEWLINE"     "DATA"

답변1

이 텍스트 처리 문제를 어렵거나 특이하게 만드는 이유는 열을 개별적으로 처리해야 한다는 것입니다.

이것은 약간의 해킹이지만 작업이 완료된 것 같습니다.

#!/bin/sh

rm -f newfile
for column in 1 2 3 4 5; do
        cut -f "$column" file |
        perl -ne 'chomp;$nl = ((tr /"/"/ % 2 == 0) ? "\n" : " "); print $_, $nl' |
        sed -e 's/[[:blank:]]*$//' -e '/^[[:blank:]]*$/d' |
        { if [ -f newfile ]; then
                paste newfile -
          else
                cat
          fi
        } >newfile.tmp
        mv newfile.tmp newfile
done

스크립트는 입력 파일이 호출 file되고 호출된 파일을 생성한다고 가정합니다(그리고 newfile임시 데이터의 파일 이름을 사용합니다). newfile.tmp또한 열이 적절하게 탭으로 구분되어 있다고 가정합니다.

원본 파일에서 탭으로 구분된 열을 하나씩 추출하는 방법을 사용합니다 cut. 각 개별 열은 짧은 Perl 스크립트를 통해 전달됩니다.

chomp;
$nl = ( ( tr /"/"/ % 2 == 0 ) ? "\n" : " " );
print $_, $nl;

이는 각 줄의 큰따옴표 수를 계산하고 줄에 짝수 개의 큰따옴표가 포함되어 있으면 추가 개행 문자와 함께 줄을 출력합니다. 따옴표 수가 홀수이면 줄 끝에 공백 문자가 추가됩니다(따라서 여러 줄에 걸쳐 따옴표 붙은 문자열이 병합됩니다). 이것은 매우 해키적인 방법입니다.

일부 정리 작업을 수행하고 sed줄 끝에서 후행 공백을 제거하고 빈 줄을 삭제합니다.

그런 다음 paste이 새 데이터를 탭으로 구분된 새 열로 만들었습니다 newfile(먼저 newfile.tmp파일로 출력한 다음 파일 이름을 바꿈). 첫 번째 열이 아직 존재하지 않는 경우에만 실행됩니다 cat.newfile

주어진 입력 데이터에 대해 열이 올바르게 탭으로 구분되어 있다고 가정하면 다음과 같은 탭으로 구분된 파일이 생성됩니다.

"column1"       "column2"       "column3"       "column4"       " column5"
"DATA"  "THIS CONTAIN NEWLINE"  "DATA"  "THIS CONTAIN NEWLINE"  "DATA"

탭을 파이프 기호로 바꿉니다(열의 시작과 끝 위치를 표시하기 위해).

$ tr '\t' '|' <newfile
"column1"|"column2"|"column3"|"column4"|" column5"
"DATA"|"THIS CONTAIN NEWLINE"|"DATA"|"THIS CONTAIN NEWLINE"|"DATA"

답변2

co=$(awk '/^[[:space:]]/{print $0}' filename |perl -pne 's/"/\n/g' |sed -r -e 's/^\s+//g' -e '/^$/d'|awk '{if(!seen[$0]++)print }')

awk -v co="$co" 'NR==1{print }/DATA/{$2=$2" "co"\"";$4=$4" "co"\"";print $0}' filename

산출

"column1"   "column2"          "column3"    "column4"           " column5"
"DATA" "THIS CONTAIN NEWLINE" "DATA" "THIS CONTAIN NEWLINE" "DATA"

답변3

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = [Z] lines.map(*.split: "\t");                 \
            @a.=map: *.join(" "); @a.=map: *.comb(/\" .+?  \"/);  \ 
            $_.join("\t").put for [Z] @a;'   file

[참고: OP에서 제공하는 파일은 파일 groff이라기보다는 출력 테이블 에 가깝습니다. tsv이것이 파일이라면 tsvrow2/column2의 내부는 \nrow2의 열 3,4,5 데이터를 다음 행으로 푸시합니다.]

이 솔루션은 입력 파일이 충분히 삭제되었다고 가정합니다. 열을 더 잘 시각화하기 위해 테이블 ​​텍스트가 단축되었습니다( "INTERNAL\nNEWLINE"대신 "THIS\nCONTAIN NEWLINE"). 하지만 내부 공백이 있는 필드에서는 코드가 계속 작동합니다. 마지막으로, 열 2와 4의 "연속"을 포함하는 세 번째 행(오버플로)에는 ""다음과 같이 열 자리 표시자가 삽입되어 있습니다.OP. 이렇게 하면 빈 문자열이더라도 행당 열당 항목이 있음을 보장합니다.

즉, 각 의 첫 번째 문에서 열은 linesplit에 있는 \t다음 [Z]압축되어 행과 열을 바꿉니다. 결과는 @a배열에 할당됩니다. 두 번째 문에서는 각 행(이전 열)이 join문자열로 결합되어 열 2와 4에서 이전에 "손상된" 큰따옴표로 묶인 데이터를 재구성합니다.

세 번째 문에서는 모든 행(이전 열)이 comb수정되었습니다. 즉, 손상되었습니다.에 대한큰따옴표로 묶인 텍스트는 한 줄에 2개의 요소를 반환합니다. 그런 다음 이 5 x 2 행/열 배열은 탭을 통해 편집된 [Z]열과 함께 2 x 5 행/열 배열로 다시 압축 축소(즉, 전치) 됩니다 .join\tput

입력 예(탭으로 구분된 열):

"column1"   "column2"   "column3"   "column4"   "column5"
"DATA1" "INTERNAL   "DATA3" "INTERNAL   "DATA5"
""  NEWLINE"    ""  NEWLINE"    ""

출력 예(탭으로 구분된 열):

"column1"   "column2"   "column3"   "column4"   "column5"
"DATA1" "INTERNAL NEWLINE"  "DATA3" "INTERNAL NEWLINE"  "DATA5"

위의 출력 열을 더 잘 시각화하는 두 가지 간단한 방법이 있습니다. 첫 번째는 |@Kusalananda처럼 파이프 문자를 연결하는 것입니다. 마지막 것을 다음 join("\t")으로 바꾸면 join("|")다음이 반환됩니다.

"column1"|"column2"|"column3"|"column4"|"column5"
"DATA1"|"INTERNAL NEWLINE"|"DATA3"|"INTERNAL NEWLINE"|"DATA5"

두 번째(아마도 더 유익한) 접근 방식은 출력에서 .raku​​or 를 호출하는 것입니다 .perl. 이는 "데이터 덤퍼"와 같은 반환(즉, Raku 데이터의 내부 표현 보기)을 제공합니다. 따라서 마지막 문에는 .raku.put for [Z] @a;다음 반환이 포함됩니다. 전송(큰따옴표 제외):

("\"column1\"", "\"column2\"", "\"column3\"", "\"column4\"", "\"column5\"")
("\"DATA1\"", "\"INTERNAL NEWLINE\"", "\"DATA3\"", "\"INTERNAL NEWLINE\"", "\"DATA5\"")

https://raku.org

관련 정보