여러 열과 1000개의 레코드가 포함된 CSV 파일이 있는데 열 중 하나(두 번째 열이라고 가정)의 모든 값 앞에 아포스트로피를 추가해야 합니다.'
첫 번째 행이나 머리글 행 외에도 간단한 행이 있을 수 있습니다. awk
또는를 사용하여 어떻게 이를 달성할 수 있습니까 sed
? 큰따옴표로 묶인 값에는 여러 개의 쉼표가 있을 수 있습니다.
견본:
"col1","col2","col3","col4","col5"
"value11","value12","value13","value14","value15"
"value21","value22","value23","value24","value25"
"value31","value32","value33","value34","value35"
예상 출력:
"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"
답변1
sed:
sed '2,$s/^\("[^"]*","\)/\1'"'"/ test.in
일부 이스케이프를 제거하려면 ERE를 사용하십시오.
sed -E '2,$s/^("[^"]*",")/\1'"'"/ test.in
이상한:
awk -F, 'NR>1{sub(/^"/,"\"'"'"'",$2)}1' test.in
인용에 대해 걱정하지 않으려면 이스케이프 코드를 사용하십시오.
awk -F, '{sub(/^"/,"\"\x27",$2)}1' test.in
답변2
펄 사용:
perl -pi -e '
BEGIN{
$column_number = 2; # Change as needed
$column_number--;
$apostrophe = chr 39;
}
next unless $this_is_data++; # Skip the first line
s@ ^((?:"[^"]+"\s*,){$column_number}) "@$1"$apostrophe@x
' your_file
이는 필드에 백슬래시로 이스케이프 처리된 따옴표가 포함되어 있지 않다고 가정합니다.
답변3
바보의 심부름은 다음과 같습니다.
$ gawk -F'","' -v var="'" -v OFS='","' 'NR>1{$2=var$2;} 1' foo.csv
이 -v
옵션을 사용하면 스크립트에 액세스할 수 있는 변수를 정의할 수 있습니다 gawk
. 이 경우 var
is '
및 OFS
(출력 필드 구분 기호)는 ","
입력 필드 구분 기호( -F
)와 동일합니다. 그런 다음 이것이 첫 번째 행( )이 아닌지 확인 하고 두 번째 열에 NR>1
값을 추가합니다 . var
결국 이것은 1
단지 속임수일 뿐이며 true로 평가되어 gawk
해당 줄이 인쇄됩니다. 하나를 추가하는 것과 동일 print;
하지만 더 짧습니다.
다른 열에서 이를 실행하려면 $2=var$2;
관심 있는 열 번호로 변경하면 됩니다 $N=var$N
.N
Perl에서도 이 작업을 수행할 수 있습니다(물론 다음과 같이 할 수 있습니다).모든 것펄에서):
$ perl -F'\",\"' -ane '$.>1 && do{$F[1]=chr(39).$F[1]};
print join("\",\"",@F)' foo.csv
이 -a
스위치는 perl이 gawk처럼 입력 라인을 분할하도록 하고, 단지 배열에 저장하도록 합니다 (perl 배열은 0에서 시작하므로 두 번째 열은 , 세 번째 열 은 등이 @F
됩니다 ). (다시 유사) 입력 필드 구분 기호를 설정합니다. 따라서 줄 번호가 1( )보다 큰지 확인하고, 그렇다면 ( a , thanks @josephR) 값을 추가합니다. 마지막으로, 결과 문자열을 사용하여 배열의 각 요소를 연결하고 인쇄합니다.$F[1]
$F[2]
-F
gawk
$.>1
chr 39
'
join
@F
","
답변4
간단한 방법은 sed
다음과 같습니다.
$ sed 's/","/","\x27/' afile
"col1","'col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"
세부 사항
우리는 첫 번째 발생을 검색 ","
하고 이를 로 대체합니다 ","`
. 그러나 백틱을 이스케이프하는 것은 까다로울 수 있습니다. 따라서 해당하는 16진수 이스케이프 코드를 입력하면 됩니다 \x27
.
너의 문제
원하는 행만 변경하도록 제한하기 위해 이와 같이 조정할 수 있습니다.
$ cat <(head -n +1 afile) <(tail -n +2 afile | sed 's/","/","\x27/')
"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"
sed
또는 팁 8-)을 알고 있다면 첫 번째 줄을 완전히 건너뛸 수 있습니다.
$ sed '2,$s/","/","\x27/' afile
"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"
이는 sed
마지막 행( $
)까지 두 번째 행을 선택하고 검색 및 바꾸기를 통해 실행하라는 의미입니다.