我们可以在awk中使用shell变量吗?

问题描述 投票:0回答:7

我们可以在 AWK 中使用像

$VAR
这样的 shell 变量来代替
$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 DBA,我们收到很多导入请求。我正在尝试使用脚本使其自动化。该脚本将找出转储中的用户,并提示需要加载转储的用户。

假设转储有两个用户

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。

awk
7个回答
140
投票

是的,您可以在 awk 中使用 shell 变量。有很多方法可以做到这一点,但我最喜欢的是使用

-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 等不同,它不是变量名称的一部分,而是 运算符


33
投票

Awk 和 Gawk 提供了

ENVIRON
关联数组来保存所有导出的环境变量。 因此,在 awk 脚本中,您可以使用
ENVIRON["VarName"]
来获取 VarName 的值,前提是 VarName 在运行 awk 之前已导出。

注意

ENVIRON
是预定义的 awk 变量,而不是 shell 环境变量。

由于我没有足够的声誉来评论其他答案,所以我必须将它们包含在这里!

显示

$ENVIRON
的早期答案是不正确的 - 该语法将由 shell 扩展,并可能导致扩展为空。

之前关于 C 无法访问环境变量的进一步评论是错误的。与上面所说的相反,C(和 C++)可以使用

getenv("VarName")
函数访问环境变量。许多其他语言提供类似的访问(例如,Java:
System.getenv()
,Python:
os.environ
,Haskell System.Environment,...)。 请注意,在所有情况下,对环境变量的访问都是只读的,您无法更改程序中的环境变量并将该值返回给调用脚本。


15
投票

有两种方法将变量传递给

awk
:一种方法是在命令行参数中定义变量:

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

另一种方法是使用

export
将 shell 变量转换为环境变量,并从
ENVIRON
数组中读取环境变量:

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

2016 年更新: OP 有逗号分隔的数据,并且想要提取给定索引的项目。该索引位于 shell 变量

NUSR
中。
NUSR
的值传递给
awk
awk
的美元运算符提取该项目。

请注意,将 UL 声明为一个包含多个元素的数组,并在

bash
中进行提取,并将
awk
完全从方程中取出,会更简单。然而,这使用基于 0 的索引。

UL=(AKHIL:AKHIL_NEW SWATHI:SWATHI_NEW)
NUSR=1
echo ${UL[NUSR]} # prints SWATHI:SWATHI_NEW

9
投票

还有另一种方法,但它可能会引起巨大的混乱:

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

因此,您暂时退出单引号环境(这通常会阻止 shell 解释 '$')以解释变量,然后返回到它。 它的优点是相对简短。


2
投票

不确定我是否理解你的问题。

但是假设我们有一个变量

number=3
并且我们想使用它而不是
$3
,在awk中我们可以使用以下代码来做到这一点

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

因此速度变量的值为 110。

希望这有帮助。


0
投票

虽然这些帖子中的大多数都是正确的,但它们似乎有点罗嗦,可能是因为它们试图通过使用用户的数据解释答案来回答用户的问题。 这是一个使用 ENVIRON 的简单示例,这是我更喜欢的方法,但有时会忘记语法:

脚本:

export MASTER="hello world"
echo "junk data" | awk '{printf("master=%s; line=%s\n", ENVIRON["MASTER"], $0)}'

结果:

master=hello world; line=junk data

-1
投票

不。您可以将 shell 变量的值传递给 awk 脚本,就像将 shell 变量的值传递给 C 程序一样,但是您无法在 awk 脚本中访问 shell 变量,就像您无法在 awk 脚本中访问 shell 变量一样。 C 程序。与 C 一样,awk 不是 shell。请参阅 comp.unix.shell 常见问题解答中的问题 24: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 声明为一个只有一个条目的数组,您可能需要重新考虑您正在尝试执行的操作,因为您可能完全采用了错误的方法。

© www.soinside.com 2019 - 2024. All rights reserved.