Bash 쉘에서 sed/awk를 사용하여 .tsv 파일에 s3 버킷 경로에 큰따옴표를 추가하는 방법

Bash 쉘에서 sed/awk를 사용하여 .tsv 파일에 s3 버킷 경로에 큰따옴표를 추가하는 방법

.tsvs3 버킷의 소스 및 대상 정보가 포함된 파일이 있습니다 . while 루프를 사용하여 해당 파일에서 소스 및 대상 경로를 읽고 s3 cp작업을 수행하고 있습니다. 파일에 100,000줄이 포함되어 있다는 점에 유의하세요.

sed모든 소스 및 대상 경로가 파일( xx.tsv) 내에서 큰따옴표로 묶이도록 명령을 어떻게 사용할 수 있습니까 ? aws s3에서는 공백이 있는 파일/폴더 이름을 "".

아래 3줄이 바뀌는 것을 찾고 있습니다.

s3://data01/repo01/image live01.png s3://Ata01/vol01/image live01.png
s3://data02/repo01/image live01.png s3://Ata02/vol01/image live01.png
s3://data03/repo01/image live01.png s3://Ata03/vol01/image live01.png

에게

"s3://data01/repo01/image live01.png" "s3://Ata01/vol01/image live01.png"
"s3://data02/repo01/image live01.png" "s3://Ata02/vol01/image live01.png"
"s3://data03/repo01/image live01.png" "s3://Ata03/vol01/image live01.png"

답변1

모든 Unix 상자의 모든 쉘에서 awk를 사용하십시오.

$ awk -F'\t' -v OFS='"\t"' '{print "\"" $1, $2 "\""}' file
"s3://data01/repo01/image live01.png"   "s3://Ata01/vol01/image live01.png"
"s3://data02/repo01/image live01.png"   "s3://Ata02/vol01/image live01.png"
"s3://data03/repo01/image live01.png"   "s3://Ata03/vol01/image live01.png"

위의 내용은 파일 이름에 탭, 개행 또는 큰따옴표가 포함되어 있지 않다고 가정합니다.

답변2

$ cat input.tsv 
s3://data01/repo01/image live01.png     s3://Ata01/vol01/image live01.png
s3://data02/repo01/image live01.png     s3://Ata02/vol01/image live01.png
s3://data03/repo01/image live01.png     s3://Ata03/vol01/image live01.png

참고: 열은 여러 공백이 아닌 탭 문자로 구분됩니다.

와 함께 sed:

$ sed -E 's/^(s3:.*)\t+(s3:.*)/"\1"\t"\2"/' input.tsv 
"s3://data01/repo01/image live01.png"   "s3://Ata01/vol01/image live01.png"
"s3://data02/repo01/image live01.png"   "s3://Ata02/vol01/image live01.png"
"s3://data03/repo01/image live01.png"   "s3://Ata03/vol01/image live01.png"

작동하는 대신 두 캡처 그룹 사이에 \s+또는 를 사용하면 동일한 출력이 생성됩니다. 즉[[:blank:]]+\t

sed -E 's/^(s3:.*)[[:blank:]]+(s3:.*)/"\1"\t"\2"/' input.tsv

그리고

sed -E 's/^(s3:.*)\s+(s3:.*)/"\1"\t"\2"/' input.tsv

버전 [[:blank:]]+은 열 구분 기호로 하나 이상의 공백 또는 탭 문자와 일치하지만 버전은 \s+하나 이상의 공백 또는 탭 문자와 일치합니다.어느공백 문자(공백, 탭 등 포함)

와 함께 awk:

$ awk -F'\t' '{print "\"" $1 "\"\t\"" $2 "\""}' input.tsv 
"s3://data01/repo01/image live01.png"   "s3://Ata01/vol01/image live01.png"
"s3://data02/repo01/image live01.png"   "s3://Ata02/vol01/image live01.png"
"s3://data03/repo01/image live01.png"   "s3://Ata03/vol01/image live01.png"

답변3

필드 구분 기호로 탭을 사용하는 CSV 파일로 데이터를 처리합니다.

csvformat -tT -U1 file.tsv >newfile.tsv

이것은 csvformat다음에서 사용됩니다.csvkit탭으로 구분된 입력( -t) 을 읽고 CSV 형식에 필요한지 여부에 관계없이 따옴표 -T로 묶인( ) 탭으로 구분된 출력( ) 을 생성합니다.-U1

파일을 CSV 파일로 취급하고 CSV 파서를 사용하여 인용을 수행하면 이미 인용된 필드를 이중으로 인용하지 않는 이점이 있습니다.

$ cat file.tsv
"s3://data01/repo01/image live01.png"   s3://Ata01/vol01/image live01.png
s3://data02/repo01/image live01.png     s3://Ata02/vol01/image live01.png
s3://data03/repo01/image live01.png     s3://Ata03/vol01/image live01.png
$ csvformat -tT -U1 file.tsv
"s3://data01/repo01/image live01.png"   "s3://Ata01/vol01/image live01.png"
"s3://data02/repo01/image live01.png"   "s3://Ata02/vol01/image live01.png"
"s3://data03/repo01/image live01.png"   "s3://Ata03/vol01/image live01.png"

또한 데이터를 있는 그대로 읽고 호출할 때 큰따옴표를 추가할 수도 있습니다 s3 cp. 그 명령이 어떤 것인지는 모르겠습니다만...

while IFS=$'\t' read -r src dst; do
    s3 cp "\"$src\"" "\"$dst\""
done <file.tsv

답변4

감자 껍질을 벗기는 방법은 여러 가지가 있지만 내 방법은

sed 's;^\(s3://.*\) \(s3://.*\)$;"\1" "\2";' filename_in.tsv > out.tsv

이는 sed입력에 정규식을 적용하여 문자열의 "s3-URL 사이의 공백이 아닌" 부분을 모두 캡처한 다음 이를 따옴표로 묶는 데 사용됩니다.

.tsv를 생성한 도구를 작성한 사람이 이것으로부터 뭔가를 배우기를 바랍니다. 예를 들어 파일 이름에 줄바꿈이 있었다면 이것은 돌이킬 수 없을 정도로 잘못되었을 수도 있습니다. 이는 파일 이름에 완벽하게 적합합니다(S3에는 없을 수도 있고, 확인하지 않았습니다).

"무엇이든 구분된" 파일에 파일 이름을 저장하면 잘못 종료됩니다(해당 구분 기호가 파일 이름에서 거의 금지된 유일한 바이트인 0바이트가 아닌 한). 이스케이프가 필요하거나 더 나은 방법은 긴 파일 이름 목록을 텍스트 파일에 저장하지 말고 sqlite로 사용하기 쉬운 것을 사용하는 것입니다.

관련 정보