Как добавить двойные кавычки в путь к корзине s3 в файле .tsv с помощью sed/awk в оболочке bash

Как добавить двойные кавычки в путь к корзине s3 в файле .tsv с помощью sed/awk в оболочке bash

У меня есть .tsvфайл, содержащий информацию об источнике и месте назначения бакета s3. Я использую цикл while для чтения пути источника и места назначения из этого файла и выполнения s3 cpоперации. Обратите внимание, что файл содержит 100 тыс. строк.

Как мне использовать 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

Использование любого awk в любой оболочке на любой машине 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"

Вышеизложенное предполагает, что ни одно из имен ваших файлов не содержит символов табуляции, новой строки или двойных кавычек.

решение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), и создания выходных данных, разделенных табуляцией ( -T), которые заключаются в кавычки ( -U1) независимо от того, требует этого формат CSV или нет.

Обработка файла как 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 это может быть не так, не проверял).

Хранение имен файлов в файлах с "чем угодно-разделителем" плохо кончится (если только этот разделитель не является нулевым байтом, который является практически единственным запрещенным байтом в именах файлов). Вам нужно экранирование или, что еще лучше, не храните длинные списки имен файлов в текстовых файлах, а используйте что-то простое для использования, например sqlite.

Связанный контент