Shell:파일에서 큰따옴표로 묶인 텍스트 안의 문자만 바꾸는 방법은 무엇입니까?

Shell:파일에서 큰따옴표로 묶인 텍스트 안의 문자만 바꾸는 방법은 무엇입니까?

텍스트 파일에 다음 줄이 있습니다

abc|45|"Do not replace | in this"|0.23

|큰따옴표로 묶인 텍스트의 문자만 바꾸는 방법을 원합니다 .

abc|45|"Do not replace in this"|0.23

이 대체 작업을 수행하는 수많은 파일과 줄이 있습니다. 어쨌든 쉘 스크립트를 사용하여 이를 달성할 수 있습니까?

답변1

새로운 답변(2022) 사용밀러먼저 헤더 없는 CSV 입력의 세 번째 필드에서 모든 파이프 기호를 제거한 다음 모든 공백을 축소합니다. 모든 인용문은 원본 텍스트로 유지됩니다.

$ mlr --csv --fs pipe -N --quote-original put '$3 = collapse_whitespace(gsub($3,"[|]",""))' file
abc|45|"Do not replace in this"|0.23

같은 일이지만 모든 필드를 반복하고 모든 문자열을 수정하려고 합니다.

$ mlr --csv --fs pipe -N --quote-original put 'for (k,v in $*) { is_string(v) { $[k] = collapse_whitespace(gsub(v,"[|]","")) } }' file
abc|45|"Do not replace in this"|0.23

내부 편집 기능을 사용하여 단일 파일에 적용하면 작동합니다.

mlr -I --csv ... *.csv

...이러한 파일이 제대로 백업되었는지 확인한 후.


이전 답변(2019):

csvformat다음에서 사용CSVKit, 그리고 sed:

$ csvformat -d '|' file | sed 's/| //' | csvformat -D '|'
abc|45|Do not replace in this|0.23

첫 번째 호출은 csvformatCSV 구분 기호를 |쉼표에서 쉼표로 변경합니다. 그런 다음 간단한 호출을 통해 파이프(및 그 뒤의 공백)를 텍스트에서 제거할 수 있습니다 sed. 그런 다음 csvformat다시 호출하여 구분 기호를 다시 변경합니다 |.

최종 출력에는 큰따옴표가 사용되지 않습니다. 더 이상 필요하지 않기 때문입니다. 처음에는 실제 데이터의 일부가 아니었지만, 사용된 파이프로 인해 필드를 분리하기만 하면 되었습니다(원본 데이터는 적절하게 참조된 CSV 파일이었습니다).

출력에서 필드를 참조하시겠습니까? -U1최종 통화와 함께 사용해 주세요 csvformat. 이는 모든 필드를 참조합니다.

답변2

간단한 바꾸기를 사용하여 및로 sed시작하는 문자열을 일치시킬 수 있습니다."아니요포함된 내용을 포함 "하고 그룹이 나타날 때까지 캡처한 다음 |거기에서 끝까지 두 번째 그룹을 일치시킵니다 ". 해당 |문자가 포함되어 있지 않으므로 일치하는 그룹을 인쇄하세요.

sed 's/\("[^"]*\).* |\([^"]*"\)/\1\2/g'

답변3

Ruby에는 훌륭한 CSV 라이브러리가 있으므로 다음과 같이 간단할 수 있습니다.

ruby -rcsv -e 'CSV.filter(col_sep: "|") {|row| row.each {|field| field.gsub!(/\| /, "")}}' file

답변4

Perl 사용(죄송합니다: 난독화된 코드)

perl -pe 's/".*?"/ $& =~ tr[|][]dr /ge'     file

설명하다:

  • perl -pe proc- proc모든 라인에 적용
  • s/RE/ f($&) /geRE- 결과로 대체f(matching string)
  • tr[|][]dr - |번역하지 않음(=삭제)

관련 정보