#csv #awk
#csv #awk
Вопрос:
Этот вопрос задавался раньше, но не совсем этот. Я новичок в написании сценариев bash и awk. Поэтому я не знаю, как полностью выполнить свою цель.
Моя цель — сгенерировать вставку sql из файла csv.
Вот мое содержимое файла csv:-
ID;NAME;AGE;TITLE;DATE;SALARY
1;Test1;36;Engineer;date '2022-10-12';50.40
2;Test2;45;Manager;date '2020-01-15';100.50
Мой сценарий awk — sql.awk:-
#!/bin/awk -f
BEGIN {
FS=";"
OFS=","
quotation="'"
}
FNR==1 {
$1=$1; head=$0
next
}
{
dat=""
for(i=1;i<=NF;i ) {
val=($i~/[[:alpha:]]$/)?quotation $i quotation:$i
dat=(dat)?dat OFS val:val
}
printf("INSERT INTO DATA ( %s) VALUES ( %s );n", head, dat) > "data.sql"
}
END {
print ENVIRON["strftime"]
printf("n-- Generated by %s at %sn", ENVIRON["USERNAME"], strftime("%Y-%m-%d %T")) >> "data.sql"
}
Этот скрипт генерирует файл data.sql с правильным содержимым в виде:
INSERT INTO DATA ( ID,NAME,AGE,TITLE,DATE,SALARY) VALUES (
1,'Test1',36,'Engineer',date '2022-10-12',50.40 );
INSERT INTO DATA ( ID,NAME,AGE,TITLE,DATE,SALARY) VALUES (
2,'Test2',45,'Manager',date '2020-01-15',100.50 );
-- Generated by usr_name at 2020-10-18 17:31:13
Моя цель — получить имя таблицы sql в качестве аргумента командной строки. Вместо ДАННЫХ жесткого кода я хочу получить их из аргумента командной строки.
Я попытался запустить это как, где приведенный выше sript изменен как:-
./sql.awk -f data.csv gievn_table_name
#!/bin/awk -f
BEGIN {
FS=";"
OFS=","
quotation="'"
tableName=ARGV[2]
}
FNR==1 {
$1=$1; head=$0
next
}
{
dat=""
for(i=1;i<=NF;i ) {
val=($i~/[[:alpha:]]$/)?quotation $i quotation:$i
dat=(dat)?dat OFS val:val
}
printf("INSERT INTO %s VALUES ( %s );n",tableName, head, dat) > tableName.sql
}
END {
print ENVIRON["strftime"]
printf("n-- Generated by %s at %sn", ENVIRON["USERNAME"], strftime("%Y-%m-%d %T")) >> tableName.sql
}
Я получил сообщение об ошибке:
./sql.awk -f data.csv gievn_table_name awk: ./sql.awk:19: printf(«ВСТАВИТЬ В %s ЗНАЧЕНИЯ ( %s );n»,имя_таблицы, head, dat) > Имя_таблицы.sql awk: ./sql.awk:19: ^ синтаксисошибка awk: ./sql.awk:23: printf(«n— Генерируется %s в %s n», ENVIRON[«USERNAME»], strftime(«%Y-%m-%d %T»)) >> Имя таблицы.sql awk: ./sql.awk:23: ^ синтаксическая ошибка awk: data.csv:2: 1;Test1;36;Инженер;дата ‘2022-10-12’;50.40 awk: data.csv:2: ^ недопустимый символ «‘ в выражении awk: data.csv:2: 1;Test2;36;Инженер;дата ‘2022-10-12’;50.40 awk: data.csv:2: ^ синтаксическая ошибка
Как получить аргумент командной строки для имени таблицы и имени выходного файла?
Комментарии:
1. Серверы баз данных имеют встроенные функции для загрузки данных из CSV, и вы должны использовать их вместо написания собственных сценариев, которые, вероятно, будут уязвимы для атак с использованием SQL-инъекций .
2. Чтобы перейти
tableName
к скрипту, используйте:./csv2sql.awk -v tableName=gievn_table_name data.csv
и в коде, который вам нужно исправить> tableName ".sql"
(и затем некоторые).3. Согласен с советом использовать
bcp
или другую утилиту, поставляемую поставщиком, но для вашего понимания используйте оболочку для передачи аргументов командной строки, сохраните выше в myAwkScript, создайте файл сценария с правильным#!/bin/bash
(или любым другим) в качестве первой строки, затем вызовите withmyAwkScript "$@"
. Вызовитеbash
скрипт, подобныйmyBashAwker f1 f2 f3 .... fn
. Удачи.4. Не используйте shebang для вызова интерпретатора awk, это только усложняет вашу жизнь. Если вы хотите, чтобы вызывалась команда оболочки, затем используйте shebang для вашей оболочки (например
#!/usr/bin/env bash
), а затем просто вызывайте awk, как из командной строки, и если вы хотите, чтобы он обрабатывал все аргументы, переданные сценарию оболочки, как аргументы для скрипта awk, затем добавьте"${@:--}"
в конце, т. е.awk 'script' "${@:--}"
.
Ответ №1:
Вам нужно сделать ARGC--
это после чтения значения из ARGV
массива, если вы не хотите, чтобы awk позже обработал его как файл. Вы можете использовать:
cat sql.awk
BEGIN {
FS=";"
OFS=","
quotation="'"
tableName=ARGV[2]
ARGC--
}
FNR==1 {
$1 = $1
head = $0
next
}
{
dat = ""
for(i=1; i<=NF; i ) {
val = ($i~/[[:alpha:]]$/) ? quotation $i quotation : $i
dat = (dat != "") ? dat OFS val : val
}
printf("INSERT INTO %s ( %s ) VALUES ( %s );n", tableName, head, dat)
}
END {
printf("n-- Generated by %s at %sn", ENVIRON["USER"], strftime("%Y-%m-%d %T"))
}
Чтобы запустить это, используйте command:
awk -f sql.awk data.csv DATA
В качестве альтернативы вы можете просто использовать более распространенную -v tableName=DATA
для вашей команды awk.
Комментарии:
1. Также для тестирования я обновил файл csv и удалил все одинарные кавычки ‘. Затем я получил эту ошибку:
./test.awk -f data.csv tablename awk: ./test.awk:5: fatal: cannot open file
tablename’ для чтения (нет такого файла или каталога)`2. @masiboo, прекратите использовать
-f
при вызове вашего скрипта. Вы указываете awk обработать файл csv как сценарий awk.3. @masiboo: Для этого используется этот скрипт:
awk -f sql.awk data.csv DATA
гдеsql.awk
находится скрипт, который я включил в свой ответ.