셸 스크립트를 사용하여 csv의 두 번째 행을 텍스트 처리하고 처리된 특정 행 결과를 CSV의 새 열에 추가하려면 어떻게 해야 합니까?

셸 스크립트를 사용하여 csv의 두 번째 행을 텍스트 처리하고 처리된 특정 행 결과를 CSV의 새 열에 추가하려면 어떻게 해야 합니까?
filename~contenturl~uuid~nodeid~contentid

000224.pdf~store://2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin~d6203724-1100-4057-9ed5-4ca6a94f5512~1324625~1363256
000238.pdf~store://2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin~96b7343d-349d-4316-8bc6-def5bd924032~1324641~1363292
000262.pdf~store://2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin~11827eee-67bb-43b7-a743-966514f26457~1324661~1363375

위는 구분 기호 "~"가 있는 .csv 파일입니다. store://에서 시작하는 두 번째 열의 하위 문자열을 만들고 해당 행의 체크섬 결과를 동일한 열에 추가하려고 합니다. 새 열은 가능하면 CSV를 사용합니다.

예를 들어

filename~contenturl~checksum
000224.pdf  /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin  23423423425

따라서 최종 결과가 표시되면 store://의 경로 부분 문자열을 만들고 해당 파일에 대한 체크섬이라는 새 열을 추가합니다.

쉘 스크립트를 통해 bin/bash를 사용하고 싶습니다

======================== 내 경우에는 방금 AWK를 사용해 보았지만 다음을 사용하여 첫 번째와 두 번째 열 값만 얻을 수 있었습니다.

awk -F "~" '{print $1, $2}'  $csv_file

이제 다음 작업은 복잡합니다. 두 번째 열 값에는 텍스트 처리가 필요하고체크섬넌 합격할 수 있어

cksum /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin

네, 제대로 들었습니다. 최종 결과는 다음과 같습니다.

filename~contenturl~checksum
000224.pdf  /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin  23423423425

다른 열의 나머지 부분도 있으면 더 좋을 것입니다. 그렇지 않으면 상위 3개 열도 괜찮을 것입니다. 참고: 기존 열을 유지하고 "체크섬"이라는 열을 더 추가해도 괜찮습니다.

답변1

해결 방법을 좀 더 쉽게 만들고 헤더 줄이 일관되지 않기 때문에(입력 파일의 줄바꿈이 잘못되고 ~출력 파일의 구분 기호가 잘못됨) 입력 파일에 헤더 줄이 없다고 가정해 보겠습니다.

이 작업은 다음 두 단계로 해결할 수 있습니다.

  1. 파일 을 만들려면 checksums.csv파일 경로만 있으면 됩니다.

    awk -F'~' '{ system("cksum /opt/xyz"substr($2,8)) }' file.csv > checksums.csv
    

    substr($2,8)접두사를 제거 store:/하고 /opt/xyz앞에 추가하여 경로를 완성합니다. 이 system(…)명령은 지정된 경로에서 명령을 실행 cksum하고 출력을 출력 파일로 리디렉션합니다.

    샘플 출력은 다음과 같습니다.

    $ cat checksums.csv
    128361894 41 /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin
    820470222 41 /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin
    1593587341 41 /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin
    

    출력에는 체크섬, 바이트 수, 경로의 3개 열이 포함되어 있으므로 다음 단계에서 세 번째와 첫 번째 열을 추출해야 합니다.

  2. 헤더 행을 인쇄하고 컬럼 1(파일 이름)을 file.csv컬럼 3(경로) 및 컬럼 1(체크섬)과 병합합니다 checksums.csv.

    { echo "filename contenturl checksum";\
      paste -d ' ' <(awk -F'~' '{ print $1 }' file.csv) <(awk '{ print $3,$1 }' checksums.csv);\
    } > newfile.csv
    

    출력 예:

    $ cat newfile.csv
    filename contenturl checksum
    000224.pdf /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 128361894
    000238.pdf /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin 820470222
    000262.pdf /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin 1593587341
    

    그런 다음 정리하십시오.

    rm checksums.csv
    

답변2

GNU에는 스크립트처럼 쉘 처리를 통합할 수 있는 명령 플래그가 sed있습니다 .escksum

sed -E 'h;s_.*~store:/([^~]*).*_cksum /opt/xyz\1_e;x;G;s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_;s/~/  /g'
  • -E가독성을 높이기 위해 확장 정규식으로 전환하는 옵션
  • h현재 행을 예약된 공간에 저장하여 원하는 대로 처리할 수 있습니다.
  • s_.*~store:/([^~]*).*_cksum /opt/xyz\1_estore:/(제거할), ()재사용할 파일 이름 \1및 나머지 줄(제거할)을 포함한 모든 항목을 일치시키고 cksum+ 경로로 바꿉니다. 이제 e플래그가 이 명령을 실행하고 패턴 공간을 반환된 내용으로 바꾸기 시작합니다.
  • x;G홀드 공간과 패턴 공간을 바꾼 다음 패턴 공간에 홀드를 추가하여 버퍼에 다음이 포함되도록 합니다.
  • s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_읽어야 할 수도 있지만 쓰기 쉽습니다. ~[^~]*두 번째 필드, (.*)\n원래 줄의 나머지 부분, (.*) .* (.*)세 개의 필드가 반환되므로 cksum두 번째 필드는 파일 이름과 체크섬으로 대체됩니다.
  • 질문에 쓰지 않았지만 예에는 ~구분 기호가 없지만 공백이 두 개 있습니다.s/~/ /g

관련 정보