Можем ли мы использовать переменные оболочки в awk?

avatar
Akhil Chinnu
3 апреля 2013 в 12:00
95222
6
68

Можем ли мы использовать переменные оболочки в AWK, такие как $VAR вместо $1, $2? Например:

UL=(AKHIL:AKHIL_NEW,SWATHI:SWATHI_NEW)

NUSR=`echo ${UL[*]}|awk -F, '{print NF}'`
echo $NUSR
echo ${UL[*]}|awk -F, '{print $NUSR}'

На самом деле я администратор базы данных Oracle, и мы получаем много запросов на импорт. Пытаюсь автоматизировать с помощью скрипта. Сценарий найдет пользователей в дампе и предложит пользователям, которым необходимо загрузить дамп.

Предположим, что в дампах есть два пользователя AKHIL, SWATHI (в дампе могут быть пользователи, и я хочу импортировать большее количество пользователей). Я хочу импортировать дампы новым пользователям AKHIL_NEW и SWATHI_NEW. Итак, ввод, который нужно прочитать, некоторые думают как AKHIL:AKHIL_NEW,SWATHI:SWATHI_NEW.

Во-первых, мне нужно найти количество пользователей, которые будут созданы, затем мне нужно получить новых пользователей, то есть AKHIL_NEW,SWATHI_NEW из введенных нами данных. Чтобы я мог подключиться к базе данных и создать новых пользователей, а затем импортировать. Я не копирую весь код: я просто скопировал код, откуда он принимает вводимых пользователей.

UL=(AKHIL:AKHIL_NEW,SWATHI:SWATHI_NEW) ## it can be many users like     USER1:USER1_NEW,USER2_USER2_NEW,USER3:USER_NEW..

NUSR=`echo ${UL[*]}|awk -F, '{print NF}'` #finding  number of fields or users
y=1
while [ $y -le $NUSR ] ; do
    USER=`echo ${UL[*]}|awk -F, -v NUSR=$y  '{print $NUSR}' |awk -F: '{print $2}'` #getting     Users to created AKHIL_NEW and SWATHI_NEW and passing to SQLPLUS
    if [[ $USER = SCPO* ]]; then
        TBS=SCPODATA
    else
        if [[ $USER = WWF* ]]; then
            TBS=WWFDATA
        else
            if [[ $USER = STSC* ]]; then
                TBS=SCPODATA
            else
                if [[ $USER = CSM* ]]; then
                    TBS=CSMDATA
                else
                    if [[ $USER = TMM* ]]; then
                        TBS=TMDATA
                    else
                        if [[ $USER = IGP* ]]; then
                        TBS=IGPDATA
                        fi
                    fi
                fi
             fi
        fi
    fi

    sqlplus -s '/ as sysdba'  <<EOF   # CREATING the USERS in the database 
    CREATE USER $USER IDENTIFIED BY $USER  DEFAULT TABLESPACE $TBS TEMPORARY TABLESPACE TEMP QUOTA 0K on SYSTEM QUOTA UNLIMITED ON $TBS;

    GRANT
    CONNECT,
       CREATE TABLE,
       CREATE VIEW,
       CREATE SYNONYM,
       CREATE SEQUENCE,
       CREATE DATABASE LINK,
       RESOURCE,
       SELECT_CATALOG_ROLE
    to $USER;
    EOF 
    y=`expr $y + 1`
done

impdp sysem/manager DIRECTORY=DATA_PUMP DUMPFILE=imp.dp logfile=impdp.log SCHEMAS=AKHIL,SWATHI REMPA_SCHEMA=${UL[*]} 

В последней команде impdp мне нужно получить исходных пользователей в дампах, то есть AKHIL, SWATHI, используя переменные.

Источник
Thor
3 апреля 2013 в 12:07
1

В чем снова был вопрос?

Jonathan Leffler
11 мая 2014 в 15:56
1

Оболочка предоставляет elif [[ $USER = WWF* ]]; then, чтобы избежать условий, выходящих за правую часть страницы и множества fi. Этот сценарий (в настоящее время) демонстрирует, почему это ценная функция.

tripleee
1 июня 2016 в 15:24
0

Возможный дубликат Как использовать переменные оболочки в сценарии awk

Dani_l
25 сентября 2019 в 04:47
0

также см. unix.stackexchange.com/questions/120788/… - использование массива ENVIRON предпочтительнее -v из-за проблем с экранированием '\'

Ответы (6)

avatar
Philip Kearns
4 августа 2017 в 11:07
9

Есть другой способ, но он может вызвать огромную путаницу:

$ VarName="howdy" ; echo | awk '{print "Just saying '$VarName'"}'
Just saying howdy
$

Итак, вы временно выходите из среды одинарных кавычек (что обычно не позволяет оболочке интерпретировать '$') для интерпретации переменной и последующего возврата в нее. Он относительно краток.

Dr_Hope
30 апреля 2018 в 06:57
0

Создает ли это какие-либо потенциальные проблемы? Кажется, пока лучший способ

Philip Kearns
3 мая 2018 в 15:28
0

Ну, первое и самое главное: это тупо. Если вы поместите его в сценарий оболочки, это может запутать чтение, а путаница может привести к ошибкам. Во-вторых, если вы поместите его в более сложное выражение, вы можете избежать кавычек и $ потенциально сделать код еще более нечитаемым.

dragon788
8 августа 2018 в 21:16
0

Я использовал это, хотя это ужасно и приведет к безумию, если вы НЕ ЧАСТО тестируете свой скрипт чем-то вроде Bats, чтобы убедиться, что ад цитат не утащил вас на 9-й уровень с Данте.

Philip Kearns
20 августа 2018 в 16:18
0

@ dragon788 Именно так :)

avatar
Anoroah
22 июля 2016 в 12:32
2

Не уверен, что понимаю ваш вопрос.

Но допустим, у нас есть переменная number=3, и мы хотим использовать ее вместо $3, в awk мы можем сделать это с помощью следующего кода

results="100 Mbits/sec 110 Mbits/sec 90 Mbits/sec"
number=3    
speed=$(echo $results | awk '{print '"\$${number}"'}')

, поэтому переменной скорости будет присвоено значение 110.

Надеюсь, это поможет.

avatar
graham hanson
26 февраля 2015 в 10:44
25

Awk и Gawk предоставляют ассоциативный массив ENVIRON, содержащий все экспортированные переменные среды. Таким образом, в вашем сценарии awk вы можете использовать ENVIRON["VarName"] для получения значения VarName, при условии, что VarName было экспортировано перед запуском awk.

Примечание. ENVIRON - это предопределенная переменная awk, НЕ переменная среды оболочки.

Поскольку у меня недостаточно репутации, чтобы комментировать другие ответы, я должен включить их сюда!

Предыдущий ответ, показывающий $ENVIRON, неверен - этот синтаксис будет расширен оболочкой и, вероятно, приведет к расширению до нуля.

Дальнейшие предыдущие комментарии о том, что C не может получить доступ к переменной среды, неверны. Вопреки сказанному выше, C (и C ++) могут обращаться к переменным среды с помощью функции getenv("VarName"). Многие другие языки предоставляют аналогичный доступ (например, Java: System.getenv(), Python: os.environ, Haskell System.Environment, ...). Обратите внимание, что во всех случаях доступ к переменным среды доступен только для чтения, вы не можете изменить переменную среды в программе и вернуть это значение в вызывающий сценарий.

akostadinov
7 июля 2016 в 13:12
2

+1, но это совершенно неверно: in all cases access to environment variables is read-only. Вы можете изменить среду, но только для текущей программы или программ, запущенных текущей программой. Тем не менее, ваша последняя строка верна, что вы не можете изменить среду текущей оболочки с помощью внешней программы. Еще одно замечание: переменная оболочки отличается от переменной среды, хотя для пользователя оболочки они выглядят одинаково и доступны одинаково (по крайней мере, в sh и подобных оболочках).

Dani_l
25 сентября 2019 в 04:45
0

Также см. unix.stackexchange.com/questions/120788/…

avatar
Ed Morton
3 апреля 2013 в 13:51
0

Нет. Вы можете передать значение переменной оболочки в сценарий awk так же, как вы можете передать значение переменной оболочки в программу на C, но вы не можете получить доступ к переменной оболочки в сценарии awk точно так же, как вы можете получить доступ к переменной оболочки в Программа C. Как и C, awk - это не оболочка. См. Вопрос 24 в FAQ по comp.unix.shell по адресу cfajohnson.com/shell/cus-faq-2.html#Q24.

Один из способов написать свой код:

UL="AKHIL:AKHIL_NEW,SWATHI:SWATHI_NEW"
NUSR=$(awk -F, -v ul="$UL" 'BEGIN{print gsub(FS,""); exit}')
echo "$NUSR"
echo "$UL" | awk -F, -v nusr="$NUSR" '{print $nusr}' # could have just done print $NF

, но с вашей исходной начальной точки:

UL=(AKHIL:AKHIL_NEW,SWATHI:SWATHI_NEW)

объявлял UL как массив с одной записью, возможно, вы захотите переосмыслить все, что вы пытаетесь сделать, поскольку у вас может быть совершенно неправильный подход.

Zenexer
23 августа 2016 в 05:59
1

Вы можете получить доступ к переменной среды из программы C. Вот для чего они были разработаны: man7.org/linux/man-pages/man3/getenv.3.html Технически среда является функцией ОС; оболочки просто интенсивно его используют и открывают для пользователя. Фактически, интерфейс основной среды доступен только для нативных программ (например, C). Все это, конечно, предполагает, что мы говорим о POSIX.

Ed Morton
23 августа 2016 в 14:47
0

Поскольку вы это знаете, я предполагаю, что вы также понимаете то, о чем я говорил, и теперь просто играете роль юриста по языку (к вашему сведению, для этого есть отличная группа новостей comp.lang.c). Да, конечно, вы можете вызвать функцию (getenv в C) или получить доступ к массиву (ENVIRON в awk), чтобы получить значение переменной оболочки в C или awk, но вы не можете использовать эту переменную оболочки непосредственно в Программа на C или сценарий awk, как в сценарии оболочки.

Zenexer
25 августа 2016 в 03:02
4

Нет, я не понимаю, что вы пытаетесь донести. Вы хотите сказать, что переменные оболочки не могут быть доступны напрямую как переменные (т.е. в нотации $)? Если так, то я не думаю, что вопрос был в этом; это скорее формальность. Как мы видели, да, можно - и довольно просто - получить доступ к среде как из awk, так и из C.

avatar
Joni
3 апреля 2013 в 12:18
13

Есть два способа передать переменные в awk: один способ - определить переменную в аргументе командной строки:

$ echo ${UL[*]}|awk -F, -v NUSR=$NUSR '{print $NUSR}'
SWATHI:SWATHI_NEW

Другой способ - преобразовать переменную оболочки в переменную среды с помощью export и прочитать переменную среды из массива ENVIRON:

$ export NUSR
$ echo ${UL[*]}|awk -F, '{print $ENVIRON["NUSR"]}'
SWATHI:SWATHI_NEW

Обновление 2016: OP имеет данные, разделенные запятыми, и хочет извлечь элемент по его индексу. Индекс находится в переменной оболочки NUSR. Значение NUSR передается в awk, а оператор доллара awk извлекает элемент.

Обратите внимание, что было бы проще объявить UL как массив из более чем одного элемента, выполнить извлечение в bash и полностью исключить awk из уравнения. Однако при этом используется индексирование на основе 0.

UL=(AKHIL:AKHIL_NEW SWATHI:SWATHI_NEW)
NUSR=1
echo ${UL[NUSR]} # prints SWATHI:SWATHI_NEW
Olivier Dulac
3 апреля 2013 в 12:45
2

не должен ли первый вместо этого быть "print NUSR"?

Joni
3 апреля 2013 в 12:49
0

Моя интерпретация вопроса заключается в том, что OP хочет, чтобы программа выполняла print $2, которая печатает вторую пару ключ: значение, а не print 2, которая печатает число 2.

Ed Morton
3 апреля 2013 в 13:29
2

Есть более 2 способов. См. Вопрос 24 в FAQ по comp.unix.shell по адресу cfajohnson.com/shell/cus-faq-2.html#Q24.

Akhil Chinnu
4 апреля 2013 в 14:05
0

Привет, Джони, твой ответ был очень полезным

Zenexer
23 августа 2016 в 06:07
1

$ не используется для доступа к переменным в awk; скорее это оператор. Это не делает того, что вы думаете. $ используется только для доступа к позиционным аргументам.

Joni
23 августа 2016 в 07:54
0

@OlivierDulac нет, должно быть print $NUSR. У OP уже есть индекс, они находятся после элемента в этом индексе.

Zenexer
25 августа 2016 в 03:04
0

@Joni Спасибо, теперь я понял.

avatar
brandizzi
3 апреля 2013 в 12:13
116

Да, вы можете использовать переменные оболочки внутри awk. Есть несколько способов сделать это, но я предпочитаю определить переменную с флагом -v:

$ echo | awk -v my_var=4 '{print "My var is " my_var}'
My var is 4

Просто передайте переменную среды в качестве параметра флагу -v. Например, если у вас есть эта переменная:

$ VAR=3
$ echo $VAR
3

Используйте это так:

$ echo | awk -v env_var="$VAR" '{print "The value of VAR is " env_var}'
The value of VAR is 3

Конечно, вы можете дать то же имя, но $ не потребуется:

$ echo | awk -v VAR="$VAR" '{print "The value of VAR is " VAR}'
The value of VAR is 3

Замечание по поводу $ в awk : в отличие от bash, Perl, PHP и т. Д., Это не часть имени переменной, а вместо этого оператор.

.
Ed Morton
3 апреля 2013 в 13:28
11

Ответ - нет! Вы можете передать значение переменной оболочки в сценарий awk так же, как вы можете передать значение переменной оболочки в программу на C, но вы не можете получить доступ к переменной оболочки в сценарии awk точно так же, как вы можете получить доступ к переменной оболочки в Программа C. Как и C, awk - это не оболочка.

Zenexer
23 августа 2016 в 05:56
3

@EdMorton Вы можете получить доступ к переменным среды в C. Это то, для чего они были изначально разработаны.

Ed Morton
23 августа 2016 в 14:23
0

Нет, переменные оболочки не предназначены для доступа программам на языке C, они предназначены для использования в сценариях оболочки. Обычно я помещаю слово directly в комментарий, чтобы попытаться подчеркнуть тот момент, что, хотя вы можете получить их значения, вызвав функцию доступа в C (getenv) или просмотрев их в массиве в некоторых awks (ENVIRON) вы не можете просто использовать их в awk или C, как вы можете в сценарии оболочки ..

Zenexer
25 августа 2016 в 03:08
0

@EdMorton "Среда" существовала до того, как появились оболочки, которые ее использовали. Оболочки были созданы частично как простой способ манипулировать окружающей средой. См. Очень краткий обзор man 7 environ.

Ed Morton
25 августа 2016 в 06:01
0

@Zenexer, вы серьезно пытаетесь превратить это в обсуждение разницы между «переменными оболочки» и «переменными среды», а также о том, что появилось раньше и что означает «доступ»? Не интересует. Если вы думаете, что можете использовать переменные оболочки внутри awk или сценариев оболочки, пожалуйста, удачи в этом.

Zenexer
30 августа 2016 в 21:54
1

@EdMorton Цель состоит в том, чтобы получить данные из оболочки в awk. Использование среды было бы простым способом передачи строковых метаданных дочернему процессу при запуске; это позволяет простая инструкция экспорта. Когда переменные оболочки экспортируются, они становятся переменными среды, но разница между ними незначительна; даже bash обрабатывает их одинаково: 1, 2 Я не пытаюсь указать на технические детали, а скорее на то, что вы усложняете вещи излишне.

Rads
2 декабря 2020 в 01:48
0

@Zenexer Вопрос заключался в том, можно ли использовать переменную оболочки без доступа. Честно говоря, ответ очень полезен для многих - и действительно решает проблему автора, поэтому кто-то должен отредактировать вопрос, чтобы обеспечить совпадение ответа и вопроса.