как передать аргумент командной строки в скрипте awk

#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 (или любым другим) в качестве первой строки, затем вызовите with myAwkScript "$@" . Вызовите 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 находится скрипт, который я включил в свой ответ.