CSV 파일의 특정 열에서 줄 바꿈을 제거하는 방법은 무엇입니까?

CSV 파일의 특정 열에서 줄 바꿈을 제거하는 방법은 무엇입니까?

줄 바꿈을 레코드 구분 기호로 사용하는 150개 이상의 열이 포함된 CSV 파일이 있습니다. 문제는 열 중 하나에 개행 문자가 포함된다는 것입니다. 그러기 위해서는 이것들을 삭제하고 싶습니다.

입력하다:

001|Baker St.
London|3|4|7
002|Penny Lane
Liverpool|88|5|7

산출:

001|Baker St. London|3|4|7
002|Penny Lane Liverpool|88|5|7

답변1

sed현재 줄에 4자가 포함되어 있지 않으면 |다음 줄을 현재 줄에 병합할 수 있습니다.

<file sed -e :1 -e 's/|/|/4;t' -e 'N;s/\n/ /;b1'

일부 sed구현에서는 파일을 제자리에 있거나 편집할 수 있으므로( -i원본 파일을 확장자로 저장하기 위해 ) 이를 사용하여 다음을 수행할 수 있습니다.-i ''-i.back.back

sed -i -e :1 -e 's/|/|/4;t' -e 'N;s/\n/ /;b1' ./*.csv

csv현재 디렉터리에서 숨겨지지 않은 모든 파일을 편집합니다 .

댓글과 동일:

<file sed '
   :1
     s/|/|/4; # replace the 4th | with itself. Only useful when combined with
              # the next "t" command which branches off if the previous
              # substitution was successful
     t
     # we only reach this point if "t" above did not branch off, that is
     # if the pattern space does not contain 4 "|"s
     N; # append the next line to the pattern space
     s/\n/ /; # replace the newline with a space

   # and then loop again in case the pattern space still does not contain
   # 4 "|"s:
   b1'

답변2

첫 번째 필드의 형식에 따라 다릅니다(각 줄이 숫자로 시작한다고 가정).

awk 'NR == 1{ printf $0; next }
     { printf "%s%s", (/^[0-9]+/? ORS : ""), $0 }
     END{ print "" }' file.csv

산출:

001|Baker St.London|3|4|7
002|Penny LaneLiverpool|88|5|7

답변3

또 다른 GNU awk솔루션은 각 레코드에 |4번 의존합니다.

awk -v RS='([^|]+\\|){4}[^|]+\n' '{gsub(/\n/," ",RT); print RT}' file

RS4개의 구분 기호를 포함하는 레코드로 설정합니다(개행 포함).

RT기록이 세워졌습니다 RS. gsub레코드에서 개행을 제거합니다.

답변4

필드가 2개만 있는 행에서 후행 개행 문자를 제거해야 한다고 가정할 수 있다면 Perl에서 다음을 수행할 수 있습니다.

$ perl -F"\|" -lane '$#F==1 ? printf : print' file.csv 
001|Baker St.London|3|4|7
002|Penny LaneLiverpool|88|5|7

중요한 면책조항: Stéphane Chazelas의 의견에서 지적했듯이 이는 입력에 %문자가 포함되어 있지 않다고 가정합니다. 왜냐하면 문자가 포함되어 있으면 해당 문자가 형식 지정자로 처리되기 때문입니다 printf. 이는 단순히 잘못된 출력을 인쇄하는 것부터 먹는 것까지 의도하지 않은 결과를 초래할 수 있습니다.RAM, 입력에 %02147483600f%02147483600f%02147483600f%02147483600f.

설명하다

  • -aperl: 와 같은 동작을 만들고 awk, 주어진 문자에서 각 입력 줄을 분할하고 -F( 여기서 a;는 perl 정규식에서 OR 을 의미하기 |때문에 이스케이프되어야 함 ) 결과를 배열로 저장합니다 .\||@F
  • -l: 각 입력 줄에서 후미 줄 바꿈을 제거하고 'n각 호출에 t를 추가합니다 print.
  • -ne: 입력 파일을 한 줄씩 읽고 주어진 스크립트를 -e각 줄에 적용합니다.
  • $#F==1 ? printf : print': $#F변수는 배열의 요소 수 @F, 즉 필드 수입니다. 따라서 이는 필드 수가 1인 경우(기존 줄이 제거되고 하나가 추가되지 않으므로 개행 없이 현재 줄을 인쇄함)를 의미 합니다 printf. 필드 수가 정확히 1이 아닌 경우 줄 바꿈이 추가되기 때문입니다 .-lprintfprint-l

동일한 내용을 다음으로 확장할 수 있습니다.

$ perl -e 'while($line=<STDIN>){
            chomp $line; 
            @fields=split(/\|/,$line); 
            if(scalar(@fields) == 2){
                print "$line";
            } 
            else{
                print "$line\n"
            }
           }' < file.csv 
001|Baker St.London|3|4|7
002|Penny LaneLiverpool|88|5|7

@Sundeep은 댓글에서 더 짧은 버전을 제안했습니다.

perl -F'\|' -ape 'chomp if $#F==1'

관련 정보