이 사이트를 처음 사용하는데 이런 질문을 해서 죄송합니다.
다음 형식의 텍스트 파일이 있습니다.
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
file
내 목표는 이 텍스트를 각 줄에 대해 값이 반복되는 CSV 형식으로 변환하는 bash 스크립트를 작성하는 것입니다 . 위의 데이터는 다음과 같아야 합니다.
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
시도해 보았지만 sed
여러 줄의 파일 이름을 기억하는 방법을 모르겠습니다. 더 쉬울 수도 있겠지만 awk
아직 깨어나지 못했습니다.
귀하의 도움에 크게 감사하겠습니다!
답변1
이러한 키가 발견될 때마다 다음 awk
명령은 awk
변수를 file
키 값으로 설정합니다 file
(키는 행의 첫 번째 필드이고 값은 두 번째 필드입니다). 현재 행에 file
키가 없으면 변수의 현재 값이 file
현재 행의 값과 함께 출력됩니다.
$ awk -F ': ' 'BEGIN { OFS="," } $1 == "file" { file = $2; next } { print file, $2 }' file
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
이는 CSV 값을 올바르게 인용하려는 시도가 아니며 필드 구분 기호 :
(콜론 + 공백)가 포함된 값이 없다고 가정합니다.
그리고 sed
:
sed -n \
-e '/^file: / { s///; h; }' \
-e '/^value: / { s///; G; s/\(.*\)\n\(.*\)/\2,\1/p; }' file
file:
행이 발견 되면 file:
접두사 문자열이 제거되고 나머지는 예약된 공간에 저장됩니다.
value:
행이 발견 되면 value:
접두사 문자열이 제거되고 예약된 공간의 텍스트가 리터럴 개행 문자를 구분 기호로 사용하여 버퍼 끝에 추가됩니다. 버퍼의 줄바꿈으로 구분된 부분이 교체되어(줄바꿈이 쉼표로 대체됨) 출력됩니다.
결과는 예상대로입니다.
key:
초기 문자열 뒤의 값에 콜론 + 공백을 포함할 수 없다는 제한이 없습니다 . 마찬가지로 최종 출력에는 CSV 텍스트의 특수 인코딩이 없으므로 쉼표와 큰따옴표가 포함된 필드는 CSV 파서를 혼란스럽게 합니다.
다음은 원본 파일의 각 줄 사이에 빈 줄을 추가하여 입력을 수정합니다. 이렇게 하면 파일이 유효한 "XTAB" 파일이 되고 :
키-값 구분 기호 역할을 합니다. 그런 다음 mlr
CSV의 특수 인용 규칙을 이해하고 XTAB 형식을 읽을 수 있는 Miller( )가 읽습니다 .
Miller는 출력에서 레코드를 읽고 awk
데이터에 "패딩" 작업을 수행하여 레코드가 없는 각 레코드에 file
이전 값을 할당합니다 .file
이후의 '필터' 작업은 필드가 없는 모든 기록을 삭제합니다 value
.
그러면 데이터가 CSV 헤더 없이 출력됩니다.
awk '{ print; print "" }' file |
mlr --ixtab --ips ': ' \
--ocsv --headerless-csv-output \
fill-down -f file then filter -x 'is_absent($value)'
입력에 쉼표와 따옴표가 포함된 경우에도 완벽하게 호환되는 CSV 출력이 올바르게 생성된다는 것을 보여주기 위해 테스트 데이터를 수정했습니다.
$ cat file
file: test: here's a test
value: this is, the value
value: another so called "value"
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
$ awk '{ print; print "" }' file | mlr --ixtab --ips ': ' --ocsv --headerless-csv-output fill-down -f file then filter -x 'is_absent($value)'
"this is, the value",test: here's a test
"another so called ""value""",test: here's a test
123,abc
234,abc
567,abc
999,def
123,ghi
999,ghi