문자열에서 \n을 제거하는 방법

문자열에서 \n을 제거하는 방법

문자열의 23열에 \n이 있는 탭으로 구분된 텍스트 파일이 있는데 이로 인해 다음 줄로 넘어갑니다.

공백이 활성화된 vi에서 텍스트 파일을 열면 DESCR2 필드의 값에 문자열을 분리하는 빈 줄이 있는 것을 볼 수 있습니다.

문자열은 탭으로 구분된 문자 내에 포함되어 있으며 \n을 제거하고 1 필드에 있는 동안 문자열을 ABC 123에 연결하려고 합니다.

나는 이것을 시도했지만 tr -d '\n' < file.txt모든 행을 1 행으로 바꿉니다. 이 열에서\n\n을 제거하고 싶습니다.

나도 시도해 보았지만 sed 's/\n\n//' file.txt효과가 없었습니다. vi에서\n\n을 검색하고 바꿀 수 있지만 sed를 사용하면 동일한 결과를 얻을 수 없습니다.

예:

\t"ABC\n
\n
123"\t

원하는 출력:

\t"ABC 123"\t

답변1

탭 문자를 필드 구분 기호로 사용하는 올바른 형식의 CSV 파일이 있는 것 같습니다. 표시된 예의 경우처럼 올바르게 인용되는 한 필드에 줄 바꿈을 포함할 수 있습니다. 모든 CSV 파서는 데이터를 읽는 데 아무런 문제가 없습니다.

이러한 개행 문자를 제거하려면 다음과 같은 CSV 파서를 사용할 수 있습니다.csvkit.

다음과 같은 샘플 파일을 사용하여 작업하겠습니다.

$ cat -t file.csv
col1^Icol2^Icol3
col1^I"ABC

123"^Icol3
col1^Icol2^Icol3

각각은 ^I탭 문자입니다. 두 번째 줄의 두 번째 필드에는 두 개의 연속된 개행 문자가 포함되어 있으며, 이를 단일 공백 ​​문자로 안전하게 대체하려고 합니다.

저는 CSV 데이터를 JSON 문서로 변환하는 csvjsonfrom 을 사용하고 있습니다. csvkit이렇게 하면 데이터를 수정하는 데 사용하기가 약간 더 쉬워지며 jq데이터를 다시 CSV 형식으로 변환하는 데에도 사용할 수 있습니다.

$ csvjson -t -H file.csv | jq -r '.[] | [ .[] | values |= gsub("\n\n";" ") ] | @csv'
"col1","col2","col3"
"col1","ABC 123","col3"
"col1","col2","col3"

여기에 사용된 명령은 csvjsonCSV 파일의 각 행을 JSON 개체로 변환합니다. 이 -t옵션은 입력이 탭 문자를 구분 기호로 사용하고 -H열 머리글이 없음을 도구에 알립니다.

JSON 개체를 배열에 넣고 읽어서 값을 추출합니다( 원본 CSV 파일에는 헤더가 없거나 질문에서 언급한 대로 적어도 없기 때문에 데이터는 , 등과 같은 키 jq에 할당됩니다 ). 공백을 사용하여 간단한 교체를 적용합니다. 연속된 개행의 모든 ​​쌍을 교체합니다.abcgsub()

gsub()분명히 위에 사용된 정규식을 변경 \n+하여 연속된 개행 문자를 단일 공백 ​​문자로 바꿀 수 있습니다.

그런 다음 운영자는 @csvCSV 출력 형식의 배열 형태로 데이터 세트를 받습니다.

csvformat기본 필드 구분 기호를 쉼표에서 다시 탭으로 변경하려면 -T(탭으로 구분된 출력의 경우) 및 (CSV 입력에 헤더 없음) 옵션을 사용하여 -H결과를 파이프하십시오 .

$ csvjson -t -H file.csv | jq -r '.[] | [ .[] | values |= gsub("\n\n";" ") ] | @csv' | csvformat -T -H
col1    col2    col3
col1    ABC 123 col3
col1    col2    col3

csvformat인용이 필요한 필드는 자동으로 인용됩니다.

csvformat도구도 마찬가지입니다 csvkit.


참고로 에서 만든 중간 JSON 문서는 csvjson다음과 같습니다( 로 미화 jq).

[
  {
    "a": "col1",
    "b": "col2",
    "c": "col3"
  },
  {
    "a": "col1",
    "b": "ABC\n\n123",
    "c": "col3"
  },
  {
    "a": "col1",
    "b": "col2",
    "c": "col3"
  }
]

답변2

GoCSV가 이를 수행할 수 있습니다.

TSV를 CSV로 변환하고 줄 바꿈을 바꿉니다.

다음과 같은 TSV 파일로 시작하여 데이터를 시뮬레이션해 보겠습니다.

+--------+--------+--------+--------+--------+
| Col21  | Col22  | DESCR2 | Col24  | Col25  |
+--------+--------+--------+--------+--------+
| data21 | data22 | ABC    | data24 | data25 |
|        |        |        |        |        |
|        |        | 123    |        |        |
+--------+--------+--------+--------+--------+

첫 번째 단계는 TSV를 모든 GoCSV 명령에서 사용되는 형식인 CSV로 변환하는 것입니다. 또한 DESC2 값을 포함하는 새 열을 끝에 추가하고 줄 바꿈을 대체했습니다. -N~이다이름새 열-티SPRIG 입니다주형replace필요한 함수를 사용하면 ( .DESCR2 | replace"DESCR2 열을 대체 함수에 넣습니다"와 같이 읽습니다):

gocsv delim   \
    -i "\t"   \
    -o ","    \
    input.tsv | 
  gocsv add                               \
    -n DESCR2_replaced                    \
    -t '{{ .DESCR2 | replace "\n" " " }}' \
  > replaced.csv

.csv 교체

+--------+--------+--------+--------+--------+-----------------+
| Col21  | Col22  | DESCR2 | Col24  | Col25  | DESCR2_replaced |
+--------+--------+--------+--------+--------+-----------------+
| data21 | data22 | ABC    | data24 | data25 | ABC  123        |
|        |        |        |        |        |                 |
|        |        | 123    |        |        |                 |
+--------+--------+--------+--------+--------+-----------------+

새 열로 교체하고 이전 열로 이름 바꾸기

_replaced 열의 데이터를 정규화한 후 "선택하다기존 DESCR2를 제거하고 새 DESCR2_replaced를 "선택"하여 교체합니다. 그런 다음이름을 바꿔라DESCR2_는 DESCR2로 다시 대체됩니다. 내 예에서는 열이 6개뿐이므로-씨 기둥색인은 23개 이상의 열 파일에 있는 색인과 다릅니다.

gocsv select     \
    -c 1-2,6,4-5 \
    replaced.csv |
  gocsv rename    \
    -c 3          \
    -names DESCR2 \
  > final.csv

최종.csv

+--------+--------+----------+--------+--------+
| Col21  | Col22  | DESCR2   | Col24  | Col25  |
+--------+--------+----------+--------+--------+
| data21 | data22 | ABC  123 | data24 | data25 |
+--------+--------+----------+--------+--------+

TSV로 다시 변환

gocsv delim   \
    -i ","    \
    -o "\t"   \
    final.csv \
  > final.tsv

큰 파이프

gocsv delim                                \
    -i "\t"                                \
    -o ","                                 \
    input.tsv                              \
| gocsv add                                \
    -n DESCR2_replaced                     \
    -t '{{ .DESCR2 | replace "\n" " " }}'  \
| gocsv select                             \
    -c 1-2,6,4-5                           \
| gocsv rename                             \
    -c 3                                   \
    -names DESCR2                          \
| gocsv delim                              \
    -i ","                                 \
    -o "\t"                                \
> final.tsv

답변3

다음을 사용해 보셨나요 sed ':a;N;$!ba;s/\\n\n/ /g' file.txt?

내가 찾은이것답변에는 sed를 사용하여 개행 문자를 제거하고 \\n추가 백슬래시를 추가하여 특수 문자를 이스케이프 처리하는 방법이 자세히 설명되어 있습니다.

답변4

간단한 sed 실행에는 패턴 공간에 언제든지 한 줄만 포함되므로 sed 구문이 작동하지 않습니다. (중복되지 않은 경우 유사한) 질문에는 sed를 사용하여 여러 줄 편집을 처리하는 방법을 설명하는 답변이 있습니다.여기. TLDR은 형편없고 구문이 고통스럽다는 것입니다.

마찬가지로 tr은 항상 하나의 행만 보기 때문에 실패합니다.

내 생각에는 여러 줄을 처리하는 가장 쉬운 방법은 Perl을 사용하는 것입니다.

perl -0777 -pe 's/\n\n/ /igs' file.txt

여기서 -0777은 Perl에게 전체 파일을 일치시키라고 지시하는 반면, -pe는 찾아서 바꾸기만 합니다.

이 버전은 인라인 편집을 위해 -i를 사용합니다.

perl -0777 -pe 's/\n\n/ /igs' -i file.txt

편집하다: 표시된 특수 문자로 바꾸려면 정규 표현식에서 해당 특수 문자를 올바르게 이스케이프 처리해야 할 수도 있습니다. \n

관련 정보