Como adicionar aspas duplas ao caminho do bucket s3 em um arquivo .tsv usando sed/awk no shell bash

Como adicionar aspas duplas ao caminho do bucket s3 em um arquivo .tsv usando sed/awk no shell bash

Eu tenho .tsvum arquivo que contém as informações de origem e destino do bucket s3. Estou usando o loop while para ler o caminho de origem e destino desse arquivo e executar s3 cpa operação. Informamos que o arquivo contém 100 mil linhas.

Como posso usar o sedcomando para que todos os caminhos de origem e destino fiquem entre aspas duplas no arquivo ( xx.tsv). Preciso das aspas duplas porque o aws s3 não pode manipular nomes de arquivos/pastas que contenham espaços em branco sem colocá-los entre "".

Estou procurando algo como abaixo de 3 linhas que serão alteradas

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

para

"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"

Responder1

Usando qualquer awk em qualquer shell em cada caixa Unix:

$ 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"

O texto acima pressupõe que nenhum dos nomes de arquivo contém tabulação, nova linha ou aspas duplas.

Responder2

$ 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

Observação: as colunas são separadas por um caractere de tabulação e não por vários espaços.

Com 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"

Usar \s+ou [[:blank:]]+entre os dois grupos de captura em vez de \ttambém funciona e produz resultados idênticos. ou seja

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

e

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

A [[:blank:]]+versão corresponderá a um ou mais caracteres de espaço ou tabulação como separador de coluna, enquanto o\s+ versão corresponderá a um ou mais dosqualquercaractere de espaço em branco (que inclui espaços, tabulações e muito mais).

com 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"

Responder3

Tratando os dados como um arquivo CSV que usa tabulações para delimitadores de campo:

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

Isso usacsvformat decsvkitpara ler a entrada delimitada por tabulação ( -t) e produz uma saída delimitada por tabulação ( -T) que está entre aspas ( -U1), independentemente de o formato CSV exigir ou não.

Tratar o arquivo como um arquivo CSV e usar um analisador CSV para fazer a cotação para você tem a vantagem de não citar campos duplamente se eles já estiverem entre aspas.

$ 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"

Obviamente, você também pode simplesmente ler os dados como estão e adicionar aspas duplas ao ligar s3 cp. Não sei como é esse comando, mas ...

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

Responder4

Há muitas maneiras de descascar essa batata, mas a minha seria

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

que usa sedpara aplicar uma expressão regular na entrada, capturando todas as partes "não o espaço entre s3-URLs" da string e, em seguida, colocando-as entre aspas.

Espero que quem escreveu as ferramentas que geraram o .tsv aprenda algo com isso - isso também poderia ter dado errado irremediavelmente, se houvesse novas linhas nos nomes dos arquivos, por exemplo, o que é perfeitamente legal para nomes de arquivos (pode não estar no S3, não verifiquei).

Armazenar nomes de arquivos em arquivos "delimitados por qualquer coisa" terminará mal (a menos que esse delimitador seja um byte 0, que é praticamente o único byte proibido em nomes de arquivos). Você precisa escapar, ou melhor ainda, não armazene longas listas de nomes de arquivos em arquivos de texto, mas use algo simples de usar como sqlite.

informação relacionada